setState的同步更新
react中的setState特点:
- 是异步操作函数;
- 组件在还没有渲染之前, this.setState 还没有被调用;
- 批量执行 State 转变时让 DOM 渲染更快(相对比一个一个的setState的来的快)。
例如:{count:0}//初始化count this.setState({count:1}); console.log(this.state.count);
setState函数并不会阻塞等待状态更新完毕。所以,打印出来的并不是count=1,而还是count=0。
很多时候,我们需要想要的state状态更新完成后再进行某些操作。此时,我们可以选择在componentWillUpdate生命周期或者componentDidUpdate生命周期的回调函数去执行我们的操作。虽然也可以达到预期效果,但是这样做不是最佳方法,代码变得破碎,可读性也不好。
因此,此时我们就需要保证setState的同步更新。
- setState支持回调函数
第一个参数是我们要设置的state,第二个参数是在状态更新完毕后的回调操作
this.setState({count:1},()=>{ console.log(this.state.count)//输出count=1 });
- ES7的Async/Await实现异步转同步
var delay = function (time) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, time); }) }; var start = async function () { console.log('a'); await delay(2000); console.log('b'); }; start();//先输出a,稍等2秒后,输出了b
同样在react中的应用:
Promise来封装setState: setStateAsync(state) { return new Promise((resolve) => { this.setState(state, resolve) }); } async componentDidMount() { await this.setStateAsync({count: 1}); console.log(this.state.count);//输出count=1 }
- async 表示这是一个async函数,await只能用在这个函数里面。
- await 表示在这里等待promise返回结果了,再继续执行。
- await 后面跟着的应该是一个promise对象
附录:
class Example extends React.Component { constructor() { super(); this.state = { val: 0 }; } componentDidMount() { this.setState({val: this.state.val + 1}); console.log(this.state.val); // 第 1 次 log->0 this.setState({val: this.state.val + 1}); console.log(this.state.val); // 第 2 次 log->0 setTimeout(() => { this.setState({val: this.state.val + 1}); console.log(this.state.val); // 第 3 次 log->2 this.setState({val: this.state.val + 1}); console.log(this.state.val); // 第 4 次 log->3 }, 0); } render() { return null; } };