从今天开始学习react,我遇到了一个可能与JS相关而不是实际反应的问题。
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时,我会得到在初始化计数器之前尝试访问计数器的引用错误。
发布于 2020-12-23 12:24:16
这是因为您尝试使用外部作用域中同名的变量: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>
发布于 2020-12-23 12:39:49
我认为这里的主要问题是如何称呼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()返回一个新的数组。您传递的函数将对数组中的每个值执行,您将决定新数组中的适当值应该是什么样的。
https://stackoverflow.com/questions/65423947
复制相似问题