React Hooks 显示不一致的行为
我想感受一下反应钩子,并通过制作一个带有添加和删除功能的普通待办事项列表来尝试它们,但我遇到了一种恼人的行为,而且我不知道其背后的逻辑。
const handleDeleteTodos = (event) => {
todos.splice(event.target.name, 1);
setTodos(todos)
window.localStorage.setItem('Todos', JSON.stringify(todos));
};
所以上面的代码确实删除了该元素,我知道这一点是因为当我重新加载页面时,该元素就消失了。但它不会像添加待办事项功能那样重新渲染。虽然下面的代码有效。
const handleDeleteTodos = (event) => {
const newTodos = [...todos];
newTodos.splice(event.target.name, 1);
setTodos(newTodos)
window.localStorage.setItem('Todos', JSON.stringify(newTodos));
};
我看到的唯一区别是代码的对象解构方面。
我只是想知道这种行为背后的逻辑是什么。
I wanted to get a feel for react hooks and was trying them out by making a normal todo list with adding and removing capabilities but I have come across an annoying behaviour and I do not know the logic behind it.
const handleDeleteTodos = (event) => {
todos.splice(event.target.name, 1);
setTodos(todos)
window.localStorage.setItem('Todos', JSON.stringify(todos));
};
So the code above does delete the element, I know this because when I reload the page, the element is gone. But it doesn't re-render like the add todo function. While the code below works.
const handleDeleteTodos = (event) => {
const newTodos = [...todos];
newTodos.splice(event.target.name, 1);
setTodos(newTodos)
window.localStorage.setItem('Todos', JSON.stringify(newTodos));
};
I only difference I see is the object destructuring aspect of the code.
I just wanted to know what is the logic behind this behaviour.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您看到 过时的道具。
使用
setState
的函数形式修改对象时无需注意(因为对该对象的引用是由 React 传递给您的)。另外,使用
useEffect
基于todos
修改localStorage
,因为它实际上是修改状态的副作用,而不是手动执行各个修改功能。You're seeing stale props.
Use the function form of
setState
to modify objects without that caveat (since the reference to that object is passed to you by React).Also, use
useEffect
to modifylocalStorage
based ontodos
, since it literally is a side effect of state being modified, instead of doing it manually in each modification function.仅当对状态对象的引用发生更改(或者如果它是标量,则值本身)时,React 才会重新渲染。
您必须创建一个新对象并将其设置为状态。
第一个示例使用相同的引用,因此 React 不知道有什么变化。
第二个示例使用新的引用。
React only rerenders if the reference to the object on state has changed (or if it's scalar, the value itself).
You must create a new object and set it on state.
The first example uses the same reference, so React has no idea anything changed.
The second example uses a new reference.
问题
Array.prototype.splice
对数组进行就地突变。Array.prototype.splice
您正在改变当前状态,然后将相同的引用保存回状态。
因为永远不会创建新的数组引用,所以 React 不会看到状态已更新。
解决方案
创建新的数组引用允许 React 使用浅引用相等性检查和重新渲染。
更传统的方法是使用
Array.prototype.filter
浅复制数组并同时删除元素。Issue
Array.prototype.splice
does an in-place mutation of the array.Array.prototype.splice
You are mutating the current state and then saving the same reference back into state.
Because a new array reference is never created, React doesn't see that state was ever updated.
Solution
Creating a new array reference allows React to use a shallow reference equality check and rerender.
A more conventional method is to use
Array.prototype.filter
to shallow copy the array and remove the element at the same time.