[英]Strange double execution of setState code in react
我有一个组件,它显示一些待办事项列表,例如
const todosData = [
{
id: 1,
text: "Take out the trash",
completed: true
},
{
id: 2,
text: "Grocery shopping",
completed: false
},
];
我有一个触发一个简单更改的按钮:它将字符“1”添加到第一个元素的文本属性。 我的处理程序看起来像这样
handleChange() {
this.setState(prevState => {
const updatedTodos = prevState.todos.map(todo => {
if (todo.id === 1) {
todo.text += 1
console.log(todo.text)
// here i get Take out the trash1, Take...trash111, Take...trash11111 and etc
}
return todo
})
return {
todos: updatedTodos
}
})
}
和简单的渲染
render() {
return (
<ul className="todo-list">
{this.state.todos.map(item => <li>{item.text}</li>)}
<button onClick={this.handleChange}>change me</button>
</ul>
)
}
所以我希望在点击后看到控制台中的“取出垃圾箱1”和页面上的相同文本。 相反,我在控制台中按预期看到“取出垃圾 1”,但在页面上我看到“取出垃圾 11”,然后“取出垃圾 1111”,因为此代码工作双倍,但是为什么在控制台中我看到第一次工作的唯一结果:“取出垃圾1”,“取出垃圾111”?
是的,我知道改变这样的项目不是正确的方法,我应该这样做
todo = {...todo, text: todo.text += 1}
如果我这样写 - 一切正常,并且这段代码还有其他不足之处,实际上这段代码不是我的,但我只是想知道这种魔法是如何发生的:
沙盒示例https://codesandbox.io/s/objective-margulis-0phvx?file=/src/App.js
这是个有趣的问题。 您可以尝试使用字母(或任何字符串),同样的事情也会发生。 你也可以在开头附加一个字符串,同样的事情也会发生。
例如
todo.text = 'boo' + todo.text + 'doo'
我完全没有受过教育的猜测是,在 React 内部的某个地方,它会进行某种字符串比较并找出差异所在; 并且可能您的代码修改了原始对象中的字符串,并且在应用它时,它会将其应用于已修改的字符串。
但是...如果我这样做:
const t = Date.now();
while(Date.now() < t + 1);
todo.text = 'a_' + todo.text + '_b_' + t;
字符串的 t 部分不会保持不变。
有趣的是,如果你这样做:
todo.text = 'a_' + todo.text + alert(todo.text);
它会发出两次警报(尽管正如您所提到的,它只发出一次 console.logs)。
所以看起来这段代码由于某种原因确实运行了两次。 我不知道为什么只有一个 console.log 消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.