在 React 组件中多次使用 this.setState 时会发生什么?

我想要检查多次使用 this.setState 时会发生什么(为了便于讨论,请使用2次)。 我以为组件会被渲染两次但显然它只被渲染了一次。我的另一个期望是,也许对 setState 的第二个调用会在第一个调用上运行,但是您已经猜到了——工作得很好。

链接到 JSfiddle

var Hello = React.createClass({
render: function() {
return (
<div>
<div>Hello {this.props.name}</div>
<CheckBox />
</div>
);
}
});


var CheckBox = React.createClass({
getInitialState: function() {
return {
alex: 0
};
},


handleChange: function(event) {
this.setState({
value: event.target.value
});
this.setState({
alex: 5
});
},


render: function() {
alert('render');
return (
<div>
<label htmlFor="alex">Alex</label>
<input type="checkbox" onChange={this.handleChange} name="alex" />
<div>{this.state.alex}</div>
</div>
);
}
});


ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);

正如您将看到的,每次渲染时都会弹出一个提示“呈现”。

你能解释一下为什么它能正常工作吗?

108851 次浏览

对事件处理程序和生命周期方法中发生的批状态更新进行反应。因此,如果在 <div onClick />处理程序中多次更新状态,React 将等待事件处理完成后再重新呈现。

需要说明的是,这只适用于由 React 控制的合成事件处理程序和生命周期方法。例如,在 AJAX 和 setTimeout事件处理程序中,状态更新不是批处理的。

更新

随着 React v18.0默认情况下,非 React 事件内的状态更新也是批处理的的释放。

档案-https://reactjs.org/blog/2022/03/29/react-v18.html#new-feature-automatic-batching

SetState ()方法不会立即更新组件的状态,它只是将更新放到一个队列中,以便稍后处理。React 可以将多个更新请求批处理在一起,以提高渲染效率。因此,在尝试根据组件以前的状态更新状态时,必须采取特殊的预防措施。

例如,下面的代码只会将 state value 属性增加1,即使它被调用了4次:

 class Counter extends React.Component{
constructor(props){
super(props)
//initial state set up
this.state = {value:0}
}
componentDidMount(){
//updating state
this.setState({value:this.state.value+1})
this.setState({value:this.state.value+1})
this.setState({value:this.state.value+1})
this.setState({value:this.state.value+1})
}
render(){
return <div>Message:{this.state.value}</div>
}
}

为了在状态被更新后使用它,执行回调参数中的所有逻辑:

//this.state.count is originally 0
this.setState({count:42}, () => {
console.log(this.state.count)
//outputs 42
})

SetState (updater,[ callback ])方法可以接受一个 updater 函数作为其第一个参数,以根据以前的状态和属性更新状态。更新程序函数的返回值将与前面的组件状态合并。该方法异步更新状态,因此在状态完全更新后将调用一个选项回调。

例如:

this.setState((prevState, props) => {
return {attribute:"value"}
})

下面是如何根据以前的状态更新状态的示例:

    class Counter extends React.Component{
constructor(props) {
super(props)
//initial state set up
this.state = {message:"initial message"}
}
componentDidMount() {
//updating state
this.setState((prevState, props) => {
return {message: prevState.message + '!'}
})
}
render(){
return <div>Message:{this.state.message}</div>
}
}