我记得当我发现setState
是异步的时,我感到非常惊讶。现在,我偶然发现了一种“奇怪”的行为,这种行为不符合我对setState
异步性的理解。
请考虑以下代码段(由于某种原因导致生成Script Error
,这是外部沙箱:https://codesandbox.io/s/zwrvkz74y3):
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
prop1: 1,
prop2: 2
};
setTimeout(this.changeProp1.bind(this), 100);
}
componentDidUpdate() {
console.info("componentDidUpdate called");
}
changeProp1() {
this.setState({ prop1: 2 });
this.changeProp2();
}
changeProp2() {
this.setState({ prop2: 3 });
}
render() {
const { prop1, prop2 } = this.state;
return React.createElement('div', null, `prop1: ${prop1}, prop2: ${prop2}`);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(React.createElement(SomeComponent), rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
如果运行此命令并检查控制台,您将看到componentDidUpdate
被调用了两次,但是setStates
是否不应该一次累积并更新组件?
更新:我认为我的困惑来自ReactJS网站上State Updates May Be Asynchronous部分的这个短语:
React可以将多个setState()调用批处理为一个更新,以提高性能。
答案 0 :(得分:1)
首先,您使用了错误的seTtimeout
表示法。它首先接受在特定时间后需要调用的函数。建议在安装组件之后执行此操作。在您的情况下,函数被调用并且不等待计时器,您可以通过将时间更改为1000ms来尝试此操作。这是正确的实现:
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
prop1: 1,
prop2: 2
};
}
componentDidMount(){
setTimeout(()=>{
this.changeProp1()
},100);
}
componentDidUpdate() {
console.info("componentDidUpdate called");
}
另外setState
仅针对诸如onClick
之类的综合事件进行批处理,并且直到处理程序执行结束时才重新呈现。对于setTimeout
和AJAX
,不会批处理状态更新。 here是有关setState
批处理的更多信息。
答案 1 :(得分:1)
如参考文献的链接部分所述,
可以 将多个setState()调用批处理为单个更新以提高性能。
至少在React 16中,它不应该批量更新状态。
正如React团队的Dan Abramov在related answer中广泛解释的那样,该状态当前仅从事件侦听器中进行批量更新,并且也在生命周期挂钩(#include <stdio.h>
int main()
{
char buffer[128];
_snprintf_s(buffer, 128, _TRUNCATE, "Hello %s!\n", "World!");
fputs(buffer, stdout);
getc(stdin);
return 0;
}
中的同步setState
调用中进行更新componentDidMount
)。预计这将在React 17中更改。
在React 16中,应明确使用componentDidUpdate
来无条件地批量更新状态(demo):
unstable_batchedUpdates