這次帶給大家React中setState使用詳解,React中setState使用的注意事項有哪些,下面就是實戰案例,一起來看一下。
class Example extends Component { contructor () { super() this.state = { value: 0, index: 0 } } componentDidMount () { this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第一次输出 this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第二次输出 setTimeout(() => { this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第三次输出 this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第四次输出 }, 0); this.refs.button.addEventListener('click', this.click) } click = () => { this.setState({value: this.state.index + 1}) this.setState({value: this.state.index + 1}) } render () { return ( <p><span>value: {this.state.value}index: {this.props.index}</span> <button>点击</button> </p> ) } }
這四次輸出,以常理來說分別是: 1,2,3,4。但是,實際輸出為: 0, 0, 2, 3
setState不會立刻改變React元件中state的值(即setState是非同步更新)
setState透過一個佇列機制實作state更新;
#當執行setState時,會將需要更新的state合併後放入狀態佇列,而不會立即更新,佇列可以有效率的批次更新state;
透過this.state直接修改的值,state不會放入狀態佇列,下次呼叫setState並對狀態佇列進行合併時,會忽略先前直接被修改的state.
setState透過引發一次元件的更新過程來引發重新繪製
此處重繪指的就是造成React的更新生命週期函數4個函數:
shouldComponentUpdate(被呼叫時this.state沒有更新;如果回傳了false,生命週期被中斷,雖然不呼叫之後的函數了,但是state仍然會被更新)
#componentWillUpdate(呼叫時this.state沒有更新)
render(被呼叫時this.state被更新)
componentDidUpdate
多個相鄰的state的修改可能會合併到一起一次執行
this.setState({name: 'Pororo'}) this.setState({age: 20})
等同於
this.setState({name: 'Pororo',age: 20})
上面兩塊程式碼的效果是一樣的。如果每次呼叫都引發一次生命週期更新,那麼效能就會消耗很大了。所以,React會將多個this.setState產生的修改放進一個佇列裡,等差不多的時候就會引發一次生命週期更新。
對於前兩次setState:
this.setState({value: this.state.val + 1}); console.log(this.state.value); // 第一次输出 this.setState({value: this.state.val + 1}); console.log(this.state.value); // 第二次输出
由於setState不會立即改變React元件中state的值,所以兩次setState中this.state.value都是同一個值0,故而,這兩次輸出都是0。因而value只加1。
既然這樣,那是不是可以直接操作this.state呢?例如:this.state.value=this.state.value 1;
這樣的確可以修改this.state.value的狀態但是卻不可以引發重複渲染。
所以,就必須透過React設定的setState函數去改變this.state,進而引發重新渲染。
setTimeout裡面的兩次setState:
setTimeout(() => { this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第三次输出 this.setState({value: this.state.value + 1}) console.log(this.state.value) // 第四次输出 }, 0);
同步更新:是由React引發的事件處理(例如:onClick引發的事件處理),呼叫setState會異步更新this.state;
非同步更新:除此之外的setState呼叫會同步執行this.setState。 「除此之外」指的是:繞過React透過addEventListener直接加入的事件處理函數和setTimeout/setInterval產生的非同步呼叫。
但是,当React在调用事件处理函数之前就会调用batchedUpdates,这个函数会把isBatchingUpdates修改为true,造成的后果就是由React控制的事件处理过程setState不会同步更新this.state。
如果this.setState的参数不是一个对象而是一个函数时,这个函数会接收到两个参数,第一个是当前的state值,第二个是当前的props,这个函数应该返回一个对象,这个对象代表想要对this.state的更改;
换句话说,之前你想给this.setState传递什么对象参数,在这种函数里就返回什么对象。不过,计算这个对象的方法有些改变,不再依赖于this.state,而是依赖于输入参数state。
function increment(state, props) { return {count: state.count + 1}; } function incrementMultiple() { this.setState(increment); this.setState(increment); this.setState(increment); }
假如当前this.state.count的值是0,第一次调用this.setState(increment),传给increment的state参数是0,第二调用时,state参数是1,第三次调用是,参数是2,最终incrementMultiple让this.state.count变成了3。
对于多次调用函数式setState的情况,React会保证调用每次increment时,state都已经合并了之前的状态修改结果。
要注意的是,在increment函数被调用时,this.state并没有被改变,依然,要等到render函数被重新执行时(或者shouldComponentUpdate函数返回false之后)才被改变。
function incrementMultiple() { this.setState(increment); this.setState(increment); this.setState({count: this.state.count + 1}); this.setState(increment); }
在几个函数式setState调用中插入一个传统式setState调用,最后得到的结果是让this.state.count增加了2,而不是增加4。
这是因为React会依次合并所有setState产生的效果,虽然前两个函数式setState调用产生的效果是count加2,但是中间出现一个传统式setState调用,一下子强行把积攒的效果清空,用count加1取代。
所以,传统式setState与函数式setState一定不要混用。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
EasyCanvas绘图库在Pixeler项目开发中使用实战总结
以上是React中setState使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!