关于javascript:你真的会用setState吗

5次阅读

共计 2642 个字符,预计需要花费 7 分钟才能阅读完成。

setState 函数是什么?

  1. 将须要解决的变动塞入组建的 state 对象中
  2. 通知该组件及其子组件须要用更新的状态来从新渲染
  3. 响应事件处理喝服务端响应更新用户界面的次要形式

setState 经典例子

constructor(props) {super(props);
    this.state = {count: 0};
    this.increase = this.increase.bind(this);
}

increase() {this.setState({ count: this.state.count + 1});
    // 第一次输入
    console.log('第一次输入:', this.state.count);
    
    this.setState({count: this.state.count + 1});
    // 第二次输入
    console.log('第二次输入:', this.state.count);
    
    setTimeout(() => {this.setState({ count: this.state.count + 1});
        // 第三次输入
        console.log('第三次输入:', this.state.count);
        
        this.setState({count: this.state.count + 1});
        // 第四次输入
        console.log('第四次输入:', this.state.count);
    }, 1000)
}

不晓得你们心里是否有下面代码的答案了呢?不错,正确输入是:0 0 2 3。那可能刚开始学 React 的童鞋就会问了?为什么后面都是 0,前面的失常加了了?那这个 setState 到底是 同步 的还是 异步 的了?那么,接下来就为你解答心中的纳闷 =。=

合并更新

前两次的 setState,不会立刻扭转 React 组件中的 state 的值,这两次输入的都是 0;合并更新,将屡次的 setState 合并成一次,不引发反复渲染

setTimeout 同步更新,引发两次渲染。

setState 是异步的吗?

其实,这只是 React 的障眼法。

setState 是同步执行的!然而 state 并不一定会同步更新(异步更新合同步更新都存在)

setState 到底干了什么了?

setState()中有个特地重要的布尔属性 isBatchingUpdates(默认为false),它决定了state同步更新 还是 异步更新

setState只在合成事件何钩子函数中是“异步更新”的。

异步更新的背地,是同步代码解决(“合成事件何钩子函数”的调用在“更新”前)。

异步是为了实现批量更新的伎俩,也是 React 新能优化的一种形式。

为什么间接批改 this.state 有效

要晓得 setState 实质是通过一个 队列机制 实现 state 更新的。执行 setState 时,会将须要更新的 state 合并 后放入状态队列,而不会立即更新 state,队列机制能够 批量更新 state。如果不通过 setState 而间接批改 this.state,那么这个state 不会放入状态队列中,下次调用 setState 时,状态队列新进行合并时,会疏忽之前间接被批改的 state,这样咱们就无奈合并了,而且理论也没有把你想要的state 更新下来。

React.setState 中的同步更新

当然了,咱们也是有方法同步获取 state 更新 后的值:

  1. setTimeout等异步操作中调用 setState 函数
  2. DOM原生事件
  3. 利用 setState 回调函数
  4. 函数式 setState 用法

前两个都是比拟好了解,因为没有前置的 batchdUpdate 调用,所以 isBatchingUpdatesfalse。不会开启批量更新模式。

前面两个办法,是 React 自身提供的。要留神的是,setState回调函数要在 render 函数 被从新执行后才执行。

// 回调函数
this.setState({count: 1}, () => {console.log(this.state.count)
})

// 函数式
this.setState(prevState => {
    return {count: prevState.count + 1}
})

比照 VUE 批量更新

Vue在监听到数据变动后,会开启一个队列,并缓冲在同一事件循环中产生的所有数据变更(如果同一个 watcher 被屡次触发,只会被推入到队列中一次)。而后,在下一次事件循环 Tick/微工作 中,Vue 刷新队列执行理论工作。

vue 批量更新体现为:

  1. Mutation Observer(变动观察器 )是侦听DOM 变动的接口。当 DOM 对象树 产生任何变动时,Mutation Observer会失去告诉。
  2. 概念上,它很靠近事件。能够了解为,当 DOM 产生变动会触发 Mutation Observer 事件。然而,它与事件有一个本质区别:事件是同步触发,DOM 发生变化会立即登程响应的事件
  3. Mutation Observer 是异步触发,DOM 产生变动,并不会立即触发,而是要等到以后所有 DOM 操作都完结后才会触发。

针对以上的知识点,咱们来看看上面这段代码,看咱们是否了解 setState:

class Demo extends React.Component {
  state = {count: 0,};
  componentDidMount() {
    this.setState({count: this.state.count + 1,});
    console.log("console:" + this.state.count);

    this.setState({count: this.state.count + 1}, () => {console.log("console from callback:" + this.state.count);
    });

    this.setState((prevState) => {console.log("console from func:" + prevState.count);
        return {count: prevState.count + 1,};
      },
      () => {console.log("last console:" + this.state.count);
      }
    );
  }

  render() {console.log("render:" + this.state.count);
    return <h4>test</h4>;
  }
}

总结

  1. state更新须要通过setState,而不能间接操作state
  2. 调用 setState 更新,state不会立即失效。
  3. 多个程序执行的 setState 不是同步一个个执行,会退出到一个队列中,而后最初一起执行,及批量更新。
正文完
 0