javascript - 使用 setState 在内部更新状态如何反应?
问题描述
在 React 中,我们使用setState
来更新组件的状态。setState
是一个异步进程,所以如果我们setState
在同一个函数中有多个。
问题:内部如何处理更新的批处理?
场景一:
componentDidMount
在同一执行周期中更新 for 循环中的状态。
class TodoApp extends React.Component {
constructor(props) {
super(props)
var state = { count: 0 };
Object.defineProperty(this, 'state', {
set: function(value) { console.log('called', value.count); state = value },
get: function() { return state; }
})
}
test() {
for (let i = 0; i< 1000; i++) {
this.setState({ count: i });
}
}
componentDidMount() {
this.test();
}
render() {
return (
<div>
{ this.state.count }
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<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>
场景二:
在 for 循环中更新状态,componentDidMount
但在不同的执行周期中。
class TodoApp extends React.Component {
constructor(props) {
super(props)
var state = { count: 0 };
Object.defineProperty(this, 'state', {
set: function(value) { console.log('called', value.count); state = value },
get: function() { return state; }
})
}
test() {
for (let i = 0; i< 1000; i++) {
this.setState({ count: i });
}
}
componentDidMount() {
setTimeout(this.test.bind(this), 0);
}
render() {
return (
<div>
{ this.state.count }
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<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>
如果您注意到场景 1 和 2,则在场景 1 中仅执行 2 次更新(假设 1 用于初始更新,其他用于最终更新)。但是,在场景 2 中,每个 setState 的状态都会发生变化/更新。
那么异步更新是如何工作的呢?什么定义了批量更新操作?
解决方案
如果您在 React 事件处理程序中,它们将被一起批处理。React 批处理在 React 事件处理程序期间完成的所有 setState,并在退出其自己的浏览器事件处理程序之前应用它们。
setTimeout 不是 React 事件处理程序,因此 React 不会在 setTimeout 回调中批处理状态更新(场景 2)。
参考:https ://github.com/facebook/react/issues/10231#issuecomment-316644950
推荐阅读
- javascript - 如何从每个类别的 Json 数组中过滤和发送数据?
- c# - 如何将数据库保存到外部存储以便用户可以看到?在 Xamarin 表单中
- three.js - Three.js 骨架动画
- node.js - 是否使用 exec() 执行猫鼬?
- ios - PDF 编辑器/在 SwiftUI 中绘制 PDF
- python - 刮取无限滚动雅虎财经历史数据
- javascript - 如何在 setState 之后在 React 中强制立即更新 DOM(即提交)?
- bash - Bash 将字符串解析为一个参数而不是两个
- python - 如何正确对齐 matplotlib 直方图中的数据?
- c# - 用不同的表解析多个 html 文档:O