简体   繁体   English

React:为什么改变状态会使组件处于如此奇怪的状态

[英]React: why is that mutating the state leaves the component in such a weird state

First, let me preemptively address this by saying that I know that we should not mutate the state.首先,让我先发制人地解决这个问题,我知道我们不应该改变状态。 I just wanted to explore what exactly would go wrong if we mutate the state directly.我只是想探索如果我们直接改变状态到底会出现什么问题。

Here I built a simple todo app.在这里,我构建了一个简单的待办事项应用程序。 The todo items are stored in an array.待办事项存储在一个数组中。 eg [{id: 0, name: 'foo'}, {id: 1, name: 'bar'}]例如[{id: 0, name: 'foo'}, {id: 1, name: 'bar'}]

To remove one todo item from the list, I think what we should do, ie the immutable way is to filter out that todo item from the list and return a copy of a new list.要从列表中删除一个待办事项,我认为我们应该做的是,即不可变的方法是从列表中过滤掉该待办事项并返回一个新列表的副本。 ie IE

setTodos((prevTodos) => prevTodos.filter((todo) => todo.id !== id));

But I was thinking that, this can be slow because it is a O(n) process.但我在想,这可能很慢,因为它是一个 O(n) 过程。 If we knew every todo item's index in the list and we can just do constant time lookup to find that item from the list and set it to null or something.如果我们知道列表中每个待办事项的索引,并且我们可以进行恒定时间查找以从列表中找到该项目并将其设置为null或其他内容。

One way to achieve this is to have a count variable starting from 0 and we use that as the id for each todo item and we increment the count every time we add a new todo.实现这一点的一种方法是拥有一个从0开始的count变量,我们将其用作每个待办事项的id ,并且每次添加新的待办事项时都会增加计数。 In this case, the id would be equal to the numeric index corresponding to the position the todo item has in the list.在这种情况下,id 将等于与待办事项在列表中的位置相对应的数字索引。 and we just grab that id and update the list directly.我们只需获取该 ID 并直接更新列表。

todos[id] = null;

However this leaves the component in a weird state, every time I remove one item, the list is actually going to be added a one todo.然而,这使组件处于一种奇怪的状态,每次我删除一个项目时,列表实际上都会添加一个待办事项。

For example, before we have [{id: 0, name:'foo'}] after we do todos[0] =null , we will end up with [null, {id: 1, name:''}]例如,在我们有[{id: 0, name:'foo'}]在我们执行todos[0] =null ,我们最终会得到[null, {id: 1, name:''}]

Here is a live demo you can play with https://codesandbox.io/s/react-todo-mutate-e0zj3?file=/src/App.js这是一个现场演示,您可以使用https://codesandbox.io/s/react-todo-mutate-e0zj3?file=/src/App.js

Can someone point out how exactly this bug happened?有人能指出这个错误究竟是怎么发生的吗?

Again I know mutating the state is not the right way to go but I just wanted to understand React more deeply so I made this little experiment.我再次知道改变状态不是正确的方法,但我只是想更深入地了解 React,所以我做了这个小实验。

This is not react behavior :).这不是反应行为:)。 Buttons have implicit type="submit".按钮具有隐式 type="submit"。 So clicking on delete button you are submitting form (adding new todo, and setting null at some index in array)所以点击删除按钮你正在提交表单(添加新的待办事项,并在数组中的某个索引处设置 null)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM