咱們先來看一個問題瀏覽器
class Test extends React.Component {
constructor(props) {異步
super(props); this.state = { num: 0, };
}
componentWillMount() {async
this.setState({ num: this.state.num + 1, }); console.log(this.state.num); this.setState({ num: this.state.num + 1, }); console.log(this.state.num);
}
render() {函數
console.log(this.state.num); return (<div />);
}
}性能
export default Test;
在上面這段代碼中3個console.log()分別打印出來的num是多少呢?this
不少人會認爲是:1 2 2,可是打印出來的是0 0 1。spa
因此咱們能夠很肯定認爲setState這個在React中用來更新state的方法是一個異步的方法。code
setState方法經過一個隊列機制實現state更新,當執行setState的時候,會將須要更新的state合併以後放入狀態隊列,而不會當即更新this.state(能夠和瀏覽器的事件隊列類比)。component
setState簡化調用棧:orm
那麼咱們要如何解決上面的問題呢?
componentWillMount() {
setTimeout(() => { this.setState({ num: this.state.num + 1, }); console.log(this.state.num); // 1 this.setState({ num: this.state.num + 1, }); console.log(this.state.num); // 2 }, 0);
}
在React的官方文檔中:
setState(updater[, callback])
updater的函數以下
(prevState, props) => stateChange
因此咱們能夠經過回調去實時獲取它更新的值:
componentWillMount() {
this.setState(((num) => { num.num++; }), () => { console.log(this.state.num); // 2 }); this.setState(((num) => { num.num++; }), () => { console.log(this.state.num); // 2 });
}
setStatePromise(updator) {
return new Promise(((resolve, reject) => { this.setState(updator, resolve); }));
}
componentWillMount() {
this.setStatePromise(({ num }) => ({ num: num + 1, })).then(() => { console.log(this.state.num); });
}
一、在State更新時,若是更新的值涉及到了state和props,我須要注意在調用setState時不要直接使用this.props和this.state,在React文檔中這樣說到:
React may batch multiple setState() calls into a single update for performance.
// React可能會將多個setState()調用批量處理爲單個更新以提升性能。
Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
// 由於this.props和this.state可能會異步更新,因此不該該依賴它們的值來計算下一個狀態。
那麼咱們怎樣去解決這個問題呢?
this.setState((prevState, props) => ({ counter: prevState.counter + props.increment}));二、若是在shouldComponentUpdate或者componentWillUpdate方法中調用setState,此時this._pending-StateQueue != null,就會形成循環調用,使得瀏覽器內存佔滿後崩潰。(親測有效)