当前位置: 首页 > 知识库问答 >
问题:

setState方法中的回调函数何时执行?

高皓
2023-03-14

在以下代码中,设置状态后,setState方法的回调不会像预期的那样执行。如果你检查控制台,你会明白我的意思。console.log读取的状态不是更新的状态。它总是前一个(你可以通过点击读取数组按钮来检查这个),但是根据反应文档:

setState()的第二个参数是一个可选的回调函数,它将在setState完成并重新呈现组件后执行。通常,我们建议对此类逻辑使用componentDidUpdate()。

虽然我知道建议使用componentDidUpdate,但我很好奇为什么它不能按预期工作,或者我是否阅读了错误的文档。通过“一旦设置状态完成”,我理解它在新状态保存后执行。

class StateAsync extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        items: [
        { text: "JavaScript" },
        { text: "React" },
        { text: "JSFiddle" },
        { text: "Awesome" }
      ],
      selectedItems: []
    }
    
    
    this.handleSelect = this.handleSelect.bind(this);
    this.test = this.test.bind(this);
  }
  
  handleSelect(e) {

        let selectedId = this.state.items[e.target.id].text;
        let clone = [...this.state.selectedItems];
        
        if(e.target.checked == false) {
          
            console.log("Removing item.");
            clone = clone.filter(item => item !== selectedId);
            this.setState({
                selectedItems: clone
            }, console.log("Remove callback result is: " + this.state.selectedItems)); //-- the callback does not execute AFTER the state is set
                       
        }else{
        
            this.setState({
                selectedItems: [...this.state.selectedItems, selectedId]
            }, console.log("Add callback result is: " + this.state.selectedItems)); //-- callback gets executed before the state is set
            console.log("Item added.");
        }
        
    }

    test(e) {
        e.preventDefault();

        console.log(this.state.selectedItems);
    }
  
  render() {
    return (
      <div>
        <span onClick={this.test} className="d-none d-md-block"><button className="btn btn-dim btn-outline-light">Read Array</button></span>
        <ol>
        {this.state.items.map((item,index) => (
          <li key={index}>
            <label>
              <input type="checkbox" onChange={this.handleSelect} id={index}/> 
              <span>{index} - {item.text}</span>
            </label>
          </li>
        ))}
        </ol>
        <span id="readout">
          
        </span>
      </div>
      
    )
  }
}

ReactDOM.render(<StateAsync />, document.querySelector("#app"))
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

这里还有一个代码:

https://codepen.io/nicholas_cb/pen/VweXoVa?editors=0010

那么,问题是setState方法中的回调是否在setState完成后执行,还是在同一时间/之前执行?

共有3个答案

潘俊
2023-03-14

回调确实在状态更改后执行。

问题是您没有添加回调。

setState(updater, [callback])
this.setState(
  { selectedItems: clone },
  // closure on this.state.selectedItems
  () => console.log("Remove callback result is: " + this.state.selectedItems)
);
吉和同
2023-03-14

这是因为您没有将回调传递给setState()方法,而是直接传递控制台。log()语句。

您需要这样做:

this.setState({
     selectedItems: clone
}, () => {
     console.log("Remove callback result is: " + this.state.selectedItems
}); //-- the callback does not execute AFTER the state is set
羊浩广
2023-03-14

您正在立即执行控制台日志,并将其返回值(未定义)作为回调传递。

这就是为什么您记录了当前状态,并且没有任何东西(未定义的作为回调)需要在更新后的状态下执行。

相反,您需要传递一个回调函数,该函数反过来调用控制台日志:

this.setState({
  selectedItems: clone
}, () => console.log("Remove callback result is: " + this.state.selectedItems)); 
 类似资料:
  • 在async-nature-of-setState中我们已经提到过, setState其实是异步的. 因为出于性能优化考虑, React会将多次setState做一次批处理. 于是setState并不会在被调用之后立即改变我们的state. 这就意味着你并不能依赖于在调用setState方法之后state, 因为此时你并不能确认该state更新与否. 当然针对这个问题我们也有解决办法—用前一个st

  • 当react组件状态发生更改时,将调用render方法。因此,对于任何状态更改,都可以在呈现方法体中执行操作。那么setState回调是否有特定的用例?

  • 本文向大家介绍Lua中让回调函数支持回调对象方法的解决方法,包括了Lua中让回调函数支持回调对象方法的解决方法的使用技巧和注意事项,需要的朋友参考一下 在 Cocos2d-Lua 中,存在很多异步或延迟的操作,例如后台加载图片、等待一定时间执行代码等。这些功能的函数通常要求传入一个 function 作为参数。 但如果我们希望这种回调支持一个对象方法,就有点小困难了。因为 Lua 的对象方法在调用

  • 本文向大家介绍jQuery Ajax Post 回调函数不执行问题的解决方法,包括了jQuery Ajax Post 回调函数不执行问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 今天在写一个检查用户名的功能时,使用的是jQuery.post( url, [data], [callback], [type] )这个函数,但是发现其中的回调函数不能执行。 先来看看我的代码: 前台代码: 后台

  • 问题内容: 我试图将一个函数传递给另一个函数,然后使传递的函数执行并传递给它一个变量。 这是我的代码: 我得到的错误是 错误是“无法将’String’的值类型转换为预期的参数类型’()’。我知道这是语法问题-只是不知道它应该是什么。 问题答案: Rob的答案是正确的,尽管我想分享一个简单的工作回调/完成处理程序的示例,但是您可以在下面下载示例项目并尝试使用的输入。 斯威夫特5: 重要说明:

  • 我需要将json对象从匿名函数加载到变量实例。 本例中的实例未定义。 我敢肯定,解决方法很简单,但是新手在节点上找不到答案…:(