The setState in React
· 2 min read
#
What在使用 React 时,并不能通过直接修改state
里的数据使页面发生更新。React 没有像 Vue 一样使用Object.defineProperty
或者
Proxy 的方式来监听数据变化。所以必须通过 setState
方法告知 React 数据已经发生了更改。
该方法是从 Component 继承来的,源码中有具体实现。
#
异步更新异步更新很好理解,
this.state = { message: "Hello World"}// ...this.setState({ message: "Hello React"})console.log(this.state.message) // Hello World
虽然已经告知 React 数据更新了,log
结果仍然是更新前的 message
。这就是因为setState
是非同步的。
#
Why is setState asynchronous- 显著提高性能
- 使props和state保持同步
U can know more in here
#
How get synchronized data- 1、get it in callback function
this.setState({ message: "Hello React"},() => { console.log(this.state.message) // Hello React})
- 2、use lifecycle function
当调用
render
function 执行完后会回调componentDidUpdate
这个生命周期函数。👇
componentDidUpdate() { console.log(this.state.message) // Hello React}
了解更多lifecycle function
#
Must setState be asynchronous- 在组件生命周期或 React 合成事件(onClick)中,
setState
是异步; - 在
setTimeout
或原生 DOM 事件中,setState
是同步🕵️♂️
changeText() { setTimeout(() => { this.setState({ message: "你好呀,李银河" }) console.log(this.state.message) // 你好呀,李银河 }, 0)}
componentDidMount() { const btnEl = document.getElementById("btn") btnEl.addEventListener('click',() => { this.setState({ message: "你好呀,李银河" }) console.log(this.state.message) // 你好呀,李银河 })}
React 源码中对这两种情况进行了判断,从而导致不同的处理方式。
#
数据合并setState
函数传入对象作为参数,为什么新的对象不对旧对象完全覆盖,而只是修改了同名属性。
其实是因为源码中使用了Object.assign()
函数。
// Object.assign({},prevState,partialState)Object.assign({},this.state,{message: "你好呀,李银河"})
state
#
Why should not change React 明确说明不推荐在 setState
中对 state
原数据(通常是引用类型)进行修改。
原因在于性能优化(或者 extends PureComponent
)时会有问题🕵️♂️
shouldComponentUpdate(newProps, newState) { // 修改相同引用类型(Array)数据并不会走下行逻辑 if(newState.books !== this.state.books){ return true } return false}
That's all