setState同步更新上文我们提到,为了提高性能,React将setState设置为批量更新,是一个异步操作函数,不能以顺序控制流的方式设置某些事件。我们也不能依赖this.state来计算未来的状态。通常情况下,比如我们希望在从服务器获取数据并渲染到界面后隐藏加载进度条或外部加载提示:componentDidMount(){fetch('https://example.com').then((res)=>res.json()).then((something)=>{this.setState({something});StatusBar.setNetworkActivityIndi??catorVisible(false);});}因为setState函数不会阻塞等待状态待更新,因此setNetworkActivityIndi??catorVisible可能会在数据呈现之前执行。我们可以选择在componentWillUpdate和componentDidUpdate这两个生命周期的回调函数中执行setNetworkActivityIndi??catorVisible,但是这样会使代码断掉,可读性不好。其实我们在项目开发中比较频繁遇到此类问题的场景是通过某个变量来控制元素的可见性:this.setState({showForm:!this.state.showForm});我们预期的效果是每个事件都是在改变表单的可见性之后触发的,但是在大型应用中如果事件的触发速度快于setState的更新速度,那么我们的值计算就完全错误了。本节讨论两种保证setState同步更新的方法。完成回调setState函数的第二个参数允许传入回调函数,在状态更新后调用,例如:this.setState({load:!this.state.load,count:this.state.count+1},()=>{console.log(this.state.count);console.log('加载完成')});这里回调函数的用法相信大家都不陌生,是JavaScript异步编程相关的知识。我们可以引入Promise来封装setState:setStateAsync(state){returnnewPromise((resolve)=>{this.setState(state,resolve)});}setStateAsync返回一个Promise对象,我们可以使用Async/Await语法来优化调用时的代码风格:asynccomponentDidMount(){StatusBar.setNetworkActivityIndi??catorVisible(true)constres=awaitfetch('https://api.ipify.org?format=json')const{ip}=awaitres.json()awaitthis.setStateAsync({ipAddress:ip})StatusBar.setNetworkActivityIndi??catorVisible(false)}这里可以保证setState渲染完成后,可以调用外部状态栏修改网络请求状态为ended。整个组件的完整定义是:classAwesomeProjectextendsComponent{state={}setStateAsync(state){...}asynccomponentDidMount(){...}render(){return(
