理解setState(),异步仍是同步?

state

state的存在是为了动态改变组件,好比根据不一样的用户操做和网络请求,来从新渲染组件。ajax

setState()是React给咱们的一个API,用来改变或定义state。promise

setState()的批量操做(batching)

在一个事件handler函数中,无论setState()被调用多少次,他们也会在函数执行结束之后,被归结为一次从新渲染, 能够优化性能, 这个等到最后一块儿执行的行为被称为batching网络

因此在函数内的setState()是有序的,若是要更改同一个state key,最后被调用的总会覆盖以前的。异步

由于batching的存在,因此这样的代码会和期待有出入。函数

//假设如今this.state.value = 0;

function eventHandler(){
    this.setState({value:this.state.value + 1});
    this.setState({value:this.state.value + 1});
    this.setState({value:this.state.value + 1});
}

//最后this.state.value仍然会是1,不是3;

因此不能依赖this.state来计算将来状态。若是想实现这样的效果,应该传一个函数给setState。这个函数有两个参数,第一个为previous state,第二个为props。这里的例子和props无关,只须要第一个参数,因此要达到效果,代码是这样性能

// 假设 this.state = { value: 0 };

function eventHandler(){
    this.setState((state) => ({ value: state.value + 1}));
    this.setState((state) => ({ value: state.value + 1}));
    this.setState((state) => ({ value: state.value + 1}));
}

//如今this.state.value === 3;

到这里咱们获得结论,setState是异步执行的。优化

如React文档所说:this

"setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains."

因此当更新state,而后想打印state的时候,应该使用回调。code

this.setState({key: val},()=>console.log(this.state));

因此setState老是异步的,吗?

当setState()不在事件Handler函数中,如在使用ajax的时候,这种batching的异步表现又不会发生component

promise.then(() => {
  // 不在事件函数中,因此setState马上执行
  this.setState({a: true}); // 从新渲染 {a: true, b: false }
  this.setState({b: true}); // 从新渲染 {a: true, b: true }
});

同步异步要分状况来看:

1. React事件函数使用,像这样用最经常使用的形式绑定函数

constructor(props){
    ...
    this.onClick = this.onClick.bind(this);
}

onClick(){
    this.setState({key:val});
}

render(){
    return(
        <div>
            <button onClick = {this.onClick}>Click me</button>
        </div>
}

这里batching发生,异步表现,是由于这种常规情景下React “知道”何时退出该事件,何时进行Batch Update原理能够参考这篇很简洁易懂的文章

2.其余情景,如上面的ajax情景,或这样用addEventListener绑定函数

componentDidMount(){
    document.querySelector('#btn').addEventListener('click,this.onClick);
}
    
    render(){
        return(
            <div>
                <button id="btn">Click me</button>
            </div>
    }
}

脱离了React的控制,React不知道如何进行Batch Update,setState()就会是同步的。

相关文章
相关标签/搜索