Learning React - ReferenceError



今天开始学习react,我遇到了一个可能与JS相关的问题,而不是实际的react。

import React, { useState } from "react";
import Counter from "./counter";
function Counters() {
const [counters, setCounters] = useState([
{ id: 1, value: 4 },
{ id: 2, value: 0 },
{ id: 3, value: 0 },
{ id: 4, value: 0 },
]);

const handleDelete = (counterID) => {
setCounters(counters.filter((counter) => counter.id !== counterID));
};
const handleIncrement = (counterToBeUpdated) => {
console.log(counters);
const counters = [...counters];
const index = counters.indexOf(counterToBeUpdated);
counters[index] = { ...counterToBeUpdated };
counters[index].value++;
setCounters({ counters });
};
return (
<div>
{counters.map((counter) => (
<Counter
key={counter.id}
counter={counter}
onDelete={handleDelete}
onIncrement={handleIncrement}
/>
))}
</div>
);
}
export default Counters;

当子组件调用handleIncrement时,我得到了在初始化计数器之前尝试访问计数器的Reference错误。

这是因为您试图从外部范围使用具有相同名称的变量:const counters = [...counters];

const counters = [1, 2, 3];
function update() {
const counters = [...counters];
}
update();
// => "Uncaught ReferenceError: Cannot access 'counters' before initialization"

您甚至不需要在增量处理程序中使用新的变量,您可以使用counters.map()来迭代元素并更新所需的值。返回的数组将是一个新数组,因此您可以将其传递给setCounters()函数。查看下面的工作演示:

function Counter({ counter, onDelete, onIncrement }) {
return (
<div>
<span style={{marginRight: '1rem'}}>{counter.value}</span>
<button onClick={() => onIncrement(counter.id)}>Inc</button>
<button onClick={() => onDelete(counter.id)}>Delete</button>
</div>
);
}
function Counters() {
const [counters, setCounters] = React.useState([
{ id: 1, value: 4 },
{ id: 2, value: 0 },
{ id: 3, value: 0 },
{ id: 4, value: 0 },
]);
const handleDelete = (id) => {
setCounters(counters.filter((counter) => counter.id !== id));
};
const handleIncrement = (id) => {
setCounters(
counters.map((counter) =>
counter.id === id ? { ...counter, value: counter.value + 1 } : counter
)
);
};
return (
<div>
{counters.map((counter) => (
<Counter
key={counter.id}
counter={counter}
onDelete={handleDelete}
onIncrement={handleIncrement}
/>
))}
</div>
);
}
ReactDOM.render(<Counters />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我认为这里的主要问题是如何调用handleIncrement。它是在没有参数的情况下调用的,这意味着counterToBeUpdated将是未定义的。

如果您将onIncrement={handleIncrement}更改为onIncrement={() => handleIncrement(counter.id)},那就成功了一半。

handleIncrement中使用counters.indexOf(counterToBeUpdated)Array.indexOf()返回作为参数传递的值的数组位置。由于您正在寻找一个对象,而对象相等是javascript中的一个重要主题,因此我建议您在这里更好地使用Array.find()

这就是在数组中查找对象的方法。

const counterToBeUpdated = counters.find((counter) => counter.id === counterToBeUpdated);

由于这种方法还有很多工作要做(增加计数器,创建带有计数器的新数组,将此数组设置为状态(,我将使用Array.map():向您展示一个快捷方式

const handleIncrement = (counterToBeUpdated) => {
setCounters(counters.map((counter) => {
if(counter.id === counterToBeUpdated){
return {
...counter,
value: counter.value + 1
};
} else {
return counter;
}
});
};

Array.map()返回一个数组。您传递的函数将针对数组中的每个值执行,您可以决定新数组中适当的值的外观。

最新更新