React setState 不适用于 if 语句
Posted
技术标签:
【中文标题】React setState 不适用于 if 语句【英文标题】:React setState doesn't work with if statement 【发布时间】:2021-09-28 00:01:04 【问题描述】:我不明白为什么下面的代码不会改变状态。即使执行“if”语句,状态也是相同的。为什么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],
;
);
当没有if
语句时,以下示例可以正常工作:
this.setState((prevState) =>
const copyItems = [...prevState.items];
copyItems[index].done = true;
return
items: [...copyItems],
;
);
在复制对象时,下面的示例可以很好地使用“if”语句:
this.setState((prevState) =>
const copyItems = JSON.parse(JSON.stringify([...prevState.items]));
copyItems[index].done = !copyItems[index].done
return
items: [...copyItems],
;
);
【问题讨论】:
你能提供你的代码的sn-p吗? 我添加了 sn-p,它工作正常。问题是由 StrictMode 引起的 【参考方案1】:问题是由使用 <React.StrictMode>
包装应用程序的 create-react-app 引起的。
要解决它,只需删除此包装标签。就是这样。 这是预期的行为,它应该有助于避免产品上的错误。更多详情React docs。
【讨论】:
删除本应有助于避免产品错误的内容听起来并不正确。 @cyberskunk ***.com/a/65167384/7399693 你的意思是什么?我知道<React.StrictMode>
是什么,并且处理双重调用的函数很烦人。但是,它确实有助于避免副作用。【参考方案2】:
React 的问题在于,即使你扩展了数组,其中的对象仍然被引用为状态中的对象。所以通过copyItems[index].done = true;
你实际上是在直接改变状态(this.state[index].done 也应该是真的)。为了避免这种情况,您可以采取的措施是在您的 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
【讨论】:
以上是关于React setState 不适用于 if 语句的主要内容,如果未能解决你的问题,请参考以下文章
getCurrentPosition 中的 React-native-maps setState 不适用于我的 url API
Coffeescript - 单击后React setState不呈现
SetState 不适用于 listview.builder