简体   繁体   English

反应中 setState 代码的奇怪双重执行

[英]Strange double execution of setState code in react

I have a component, which displays some todos list like我有一个组件,它显示一些待办事项列表,例如

const todosData = [
  {
      id: 1,
      text: "Take out the trash",
      completed: true
  },
  {
      id: 2,
      text: "Grocery shopping",
      completed: false
  },
];

And I have a button that triggers one simple change: it adds char "1" to the text property of the first element.我有一个触发一个简单更改的按钮:它将字符“1”添加到第一个元素的文本属性。 And my handler looks like this我的处理程序看起来像这样

    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
          }
      })
  }

and simple rendering和简单的渲染

render() { 
        return (
            <ul className="todo-list">
              {this.state.todos.map(item => <li>{item.text}</li>)}
              <button onClick={this.handleChange}>change me</button>  
            </ul>
        )    
    }

so i expect after clicking to see "Take out the trash1" in console and the same text on the page.所以我希望在点击后看到控制台中的“取出垃圾箱1”和页面上的相同文本。 Instead of this i see "Take out the trash1" in console as expected, but on the page i see "Take out the trash11", and then "Take out the trash1111" as this code works double, but then why in console i see only result of first work: "Take out the trash1", "Take out the trash111"?相反,我在控制台中按预期看到“取出垃圾 1”,但在页面上我看到“取出垃圾 11”,然后“取出垃圾 1111”,因为此代码工作双倍,但是为什么在控制台中我看到第一次工作的唯一结果:“取出垃圾1”,“取出垃圾111”?

Yes, i understand that it is not right way to change item like this and i should do是的,我知道改变这样的项目不是正确的方法,我应该这样做

todo = {...todo, text: todo.text += 1} 

and if i write this way - everything works correct, and there are other lacks in this code and actually this code is not mine, but i just wonder how this magic happens:如果我这样写 - 一切正常,并且这段代码还有其他不足之处,实际上这段代码不是我的,但我只是想知道这种魔法是如何发生的:

  1. why it works twice为什么它工作两次
  2. why i see only first output in console为什么我在控制台中只看到第一个输出

The sandbox example https://codesandbox.io/s/objective-margulis-0phvx?file=/src/App.js沙盒示例https://codesandbox.io/s/objective-margulis-0phvx?file=/src/App.js

This is an interesting question.这是个有趣的问题。 You can try with a letter (or any string) and the same thing will happen.您可以尝试使用字母(或任何字符串),同样的事情也会发生。 You can also append a string to the start and the same thing will happen.你也可以在开头附加一个字符串,同样的事情也会发生。

eg例如

todo.text = 'boo' + todo.text + 'doo'

My completely uneducated guess was that somewhere in the internals of React it does some kind of string comparison and works out what the difference is;我完全没有受过教育的猜测是,在 React 内部的某个地方,它会进行某种字符串比较并找出差异所在; and that maybe your code modifies the string in the original object, and that by the time it comes to apply it, it applies it to the already modified string.并且可能您的代码修改了原始对象中的字符串,并且在应用它时,它会将其应用于已修改的字符串。

But... if I do:但是...如果我这样做:

const t = Date.now();
while(Date.now() < t + 1);
todo.text = 'a_' + todo.text + '_b_' + t;

The t portion of the string does not stay the same.字符串的 t 部分不会保持不变。

Interestingly, if you do:有趣的是,如果你这样做:

todo.text = 'a_' + todo.text + alert(todo.text);

It does alert twice (even though, as you've mentioned, it only console.logs once).发出两次警报(尽管正如您所提到的,它只发出一次 console.logs)。

So it looks like this code does run twice for some reason.所以看起来这段代码由于某种原因确实运行了两次。 I've no idea why there's only one console.log message.我不知道为什么只有一个 console.log 消息。

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

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