React.js学习

为什么React.setState是异步的?

2019-03-08  本文已影响6人  小进进不将就

(1)保证内部的一致性
目前 React 提供的 objects 有三种:① statepropsrefs
这三个 object 的行为和表现都是一致的,它们能够保证构建出协调的树(reconciled tree),这非常重要。

class Child extends React.Component{
  state={value:0,}
  this.setState({ value: this.state.value + 1 }) // 1 
  this.setState({ value: this.state.value + 1 }) // 2
}

如果父组件也需要该 statevalue 属性的话,就需要 状态提升:
父:

class Father extends React.Component{
  state={value:0,}
  Add(){
     this.setState({ value: this.state.value + 1 })
  } 
  render(){
    return (<Child add={this.Add.bind(this)}/>)
  }
}

子:

class Child extends React.Component{
  this.props.add()
}

注意:虽然在此假设中 state 是同步的,会立即更新,但是 props 却不会立即更新,而是 0

this.props.onIncrement() // 0
this.props.onIncrement() // 0

为啥?
因为 在没有重新渲染 父组件 的情况下,React 不会立即更新 props,如果 将 props 也设为同步更新的话,那么就必须放弃 批处理(batching)。
stateprops 变化一次,就重渲染一次,这会显著地降低 React 性能。

this.setState({this.state.value+this.props.value})

在此假设中 state 是立即更新的,但 props 不是,这就会导致 新的 state 的值不是期待的值。

综上:React 采用了 stateprops 采用 异步更新 的策略,保证内部一致性、保证状态提升更加安全。

(2)能够使用并发更新,从而优化性能
我们可能认为 状态更新是按照一定顺序更新的,但事实上,React 会根据不同的调用源,给不同的 setState() 分配不同的优先级。(妈的,我在上一篇文章还说 React 是顺序更新 state 的。。

调用源:事件处理、网络请求、动画 等。

React可能在 v17 的时候推出异步渲染 UI,这受益于 stateprops 的异步更新。

异步渲染 UI 有什么用?

但是,如果网络请求非常快的话,loading 效果会闪烁一下,再呈现 页面B,这会影响用户体验。

如果 React 有了 异步渲染 UI 的功能,那么当你 setState() 的时候,React 会“偷偷地”渲染 页面B:
如果 渲染 页面B 花费的时间较长,那么开发者可以 加一个 loading 效果;
如果 渲染 页面B 花费的时间hin短,那么 React 偷偷渲染好 页面B 后,可以无缝切换到页面B。

同时,异步渲染 还能让用户在等待的过程中,继续和 旧页面 交互。

综上:如果 同步更新 state 的话,就无法在幕后渲染新页面,同时还保持旧页面的交互。

参考:https://github.com/facebook/react/issues/11527#issuecomment-360199710


(完)

上一篇下一篇

猜你喜欢

热点阅读