[英]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.