setState()更新狀態的2種寫法
- setState(updater, [callback]), updater為返回stateChange對象的函數: (state, props) => stateChange 接收的state和props被保證為最新的
- setState(stateChange, [callback]) stateChange為對象, callback是可選的回調函數, 在狀態更新且界面更新后才執行
- 總結: 對象方式是函數方式的簡寫方式 如果新狀態不依賴於原狀態 ===> 使用對象方式 如果新狀態依賴於原狀態 ===> 使用函數方式 如果需要在setState()后獲取最新的狀態數據, 在第二個callback函數中讀取
setState()更新狀態是異步還是同步的?
- 執行setState()的位置? 在react控制的回調函數中: 生命周期勾子 / react事件監聽回調 非react控制的異步回調函數中: 定時器回調 / 原生事件監聽回調 / promise回調
- 異步 OR 同步? react相關回調中: 異步 其它異步回調中: 同步
關於異步的setState()
- 多次調用, 如何處理? setState({}): 合並更新一次狀態, 只調用一次render()更新界面 ---狀態更新和界面更新都合並了 setState(fn): 更新多次狀態, 但只調用一次render()更新界面 ---狀態更新沒有合並, 但界面更新合並了
- 如何得到異步更新后的狀態數據? 在setState()的callback回調函數中
面試題
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>03_setState()面試題</title> </head> <body>
<div id="example"></div>
<script type="text/javascript" src="./js/react.development.js"></script>
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<script type="text/javascript" src="./js/babel.min.js"></script><script type="text/babel">
class StateTest extends React.Component {state = { count: 0, } componentDidMount() { this.setState({count: this.state.count + 1}) this.setState({count: this.state.count + 1}) console.log(this.state.count) // 2 ==> 0 this.setState(state => ({count: state.count + 1})) this.setState(state => ({count: state.count + 1})) console.log(this.state.count) // 3 ==> 0 setTimeout(() => { this.setState({count: this.state.count + 1}) console.log('timeout', this.state.count) // 10 ==> 6 this.setState({count: this.state.count + 1}) console.log('timeout', this.state.count) // 12 ==> 7 }, 0) Promise.resolve().then(value => { this.setState({count: this.state.count + 1}) console.log('promise', this.state.count) // 6 ==>4 this.setState({count: this.state.count + 1}) console.log('promise', this.state.count) // 8 ==> 5 }) } render() { const count = this.state.count console.log('render', count) // 1 ==> 0 4 ==>3 5 ==>4 7 ==>5 9 ==>6 11 ==>7 return ( <div> <p>{count}</p> </div> ) }
}
ReactDOM.render(<StateTest/>, document.getElementById('example'))
</script>
</body>
</html>