[英]React setState doesn't work with if statement
I don't understand why below code doesn't change state.我不明白为什么下面的代码不会改变状态。 Even when 'if' statement is executed, state is the same.
即使执行“if”语句,状态也是一样的。 Why case with
if
doesn't change state?为什么
if
情况不会改变状态?
class Welcome extends React.Component { state = { items: [ { id: 1, done: false, }, { id: 2, done: false, }, { id: 3, done: false, }, ] } handleDone = (index) => { this.setState((prevState) => { const copyItems = [...prevState.items]; if (copyItems[index].done === false) { console.log("Done should be true"); copyItems[index].done = true; } else { console.log("Done should be false"); copyItems[index].done = false; } // copyItems[index].done = !copyItems[index].done - the same result return { items: [...copyItems], }; }); } render() { return ( this.state.items.map((item, index) => { return ( <div> <span>id: {item.id}</span> <span> {item.done ? "- is not done" : "- is done"} </span> <button onClick={() => this.handleDone(index)}> Change to opposite </button> </div> ) }) ) } } ReactDOM.render(<Welcome />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
this.setState((prevState) => {
const copyItems = [...prevState.items];
if (copyItems[index].done === false) {
console.log("Done should be true");
copyItems[index].done = true;
} else {
console.log("Done should be false");
copyItems[index].done = false;
}
// copyItems[index].done = !copyItems[index].done - the same result
return {
items: [...copyItems],
};
});
Below example works fine when there is no if
statement:当没有
if
语句时,下面的示例工作正常:
this.setState((prevState) => {
const copyItems = [...prevState.items];
copyItems[index].done = true;
return {
items: [...copyItems],
};
});
Below example works fine with 'if' statement in case when object is copied:下面的示例适用于“if”语句,以防复制对象:
this.setState((prevState) => {
const copyItems = JSON.parse(JSON.stringify([...prevState.items]));
copyItems[index].done = !copyItems[index].done
return {
items: [...copyItems],
};
});
What's wrong for React is that even if you spread your array, the object inside it are still referenced as the object inside your state. React 的错误在于,即使您展开数组,其中的对象仍然被引用为您状态中的对象。 So by doing
copyItems[index].done = true;
所以通过执行
copyItems[index].done = true;
you're actually mutating the state directly (this.state[index].done should be true also).你实际上是直接改变状态(this.state[index].done 也应该是真的)。 What you can do to avoid this is to use .map on your prevState so you're not updating the state directly.
为了避免这种情况,您可以做的是在 prevState 上使用 .map ,这样您就不会直接更新状态。
const state = [{ done: true }]; const stateCopy = [...state]; const toFind = 0; stateCopy[toFind].done = false; console.log(stateCopy[toFind], state[toFind]); // { done: false } , { done: false } /!\\ state should not be updated at this point. // good way of doing that might be by using prevState.items.map() and do your logic inside it const stateUpdated = state.map((el, index) => { if (index === toFind) { return { done: !el.done } } return el; }); console.log(stateUpdated[toFind], state[toFind]) // state is not mutated, as expected
Problem was caused by create-react-app that wrap app with <React.StrictMode>
.问题是由使用
<React.StrictMode>
包装应用程序的 create-react-app 引起的。
To resolve it just remove this wrapping tag.要解决它,只需删除此包装标签。 And that's it.
就是这样。 It's expected behaviour and it should help avoid bugs on prod.
这是预期的行为,它应该有助于避免产品上的错误。 More details in React docs .
React 文档中的更多详细信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.