react循环setstate_react -- 关于兄弟组件触发更新的问题
大家在用react的時候,應(yīng)該都知道react的state更新會由父到子逐級更新的事情,那么就會有這樣一個問題,當(dāng)要渲染的頁面元素較多,極端情況下,特別是大數(shù)據(jù)展示的時候,由頂層一點點逐級渲染,性能消耗太大。打個具體點的比方,有A,B,C三個組件,A是B,C的父組件,當(dāng)應(yīng)用場景是,B的某個動作需要C來相應(yīng)的時候,傳統(tǒng)的做法如下。
class A extends React.Component {constructor(props) {super(props)this.state = {X: "",}}onChangeX=(v)=>{this.setState({X:v})}render() {return <div><B onChangeX={this.onChangeX}/><C X={this.state.X}/></div>} }class B extends React.Component {render() {return <div onClick={this.props.onChangeX}>{sample}</div>} } class C extends React.Component {render() {return <div>{this.props.X}</div>} }在這種代碼的實現(xiàn)下,由B觸發(fā)的事件必須經(jīng)過父組件A所緩存的狀態(tài)才能更新到C,如果A本身Render的性能消耗大的話,比如A本身有很多的邏輯計算 或者A下面還有其它組件D,E,F,G,畫面渲染就非常耗時。那么有沒有什么辦法讓B觸發(fā),繞過父組件A只更新目標C呢。
本人這里有兩個方案可供選擇。
第一,走redux
讓觸發(fā)點B不直接調(diào)用A的內(nèi)部方法,而是發(fā)送redux更新用的Action。同時在被渲染的C組件外層包裹一個直接接收redux數(shù)據(jù)的container,數(shù)據(jù)由redux傳給C。關(guān)于redux和container就暫時不寫入代碼了(偷個懶)
class A extends React.Component {constructor(props) {super(props)this.state = {}}render() {return <div><B/><C/></div>} }class B extends React.Component {render() {return <div onClick={this.props.onChangeXAction}>{sample}</div>} } class C extends React.Component {render() {return <div>{this.props.X}</div>} }這個方法的好處是,條理清晰,代碼好讀。壞處是副作用太大,首先是當(dāng)組件存在于一個比較大的應(yīng)用的時候,redux的負擔(dān)過重,影響反應(yīng)時間。其次是要想達到不觸發(fā)父組件A的目的,A本身就不能跟redux關(guān)聯(lián),否則,redux的狀態(tài)動了,在沒有特殊控制的情況下,A也會被觸發(fā)更新。
第二個方法,把被渲染組件C的this傳給A,然后緩存下來。當(dāng)被觸發(fā)的時候調(diào)用C自身的setState方法更新。代碼如下:
class A extends React.Component {constructor(props) {super(props)this.state = {// 組件C的對象緩存cInst: "",}}setCInst=(inst)=>{// 給緩存賦值this.setState({cInst:inst})}onChangeX=(v)=>{//由C自身對象的setState方法進行renderthis.cInst.setState({X:v})}render() {return <div><B onChangeX={this.onChangeX}/><C setCInst={this.setCInst}/></div>} }class B extends React.Component {render() {return <div onClick={this.props.onChangeX}>{sample}</div>} } class C extends React.Component {constructor(props) {super(props)this.state = {X: "",}}componentDidMount() {this.props.setCInst(this)}render() {return <div>{this.state.X}</div>} }這樣一來,當(dāng)B開始觸發(fā)的時候,因為沒有調(diào)用A的setstate方法,A就不會重新渲染,從而達到提高性能的目的。當(dāng)然,這種方法也有缺點,C組件的緩存是在componentDidMount生命周期上掛載的,那么在寫父組件的時候就要特別小心。比如本人在另一篇文章中【getDerivedStateFromProps 如何區(qū)分狀態(tài)更新來源】
閆松:react -- getDerivedStateFromProps 如何區(qū)分狀態(tài)更新來源?zhuanlan.zhihu.com之中寫到的方法,用隨機標志位來判斷區(qū)分跟新元,就不適用上面的代碼。原因是,當(dāng)給子組件C加上key=隨機標志位 之后。每次A在渲染的時候,都會生成新的key。當(dāng)新key生成的時候,react認為以前的子組件已經(jīng)被拋棄了。會生成新的子組件,這時候新的子組件會重新執(zhí)行componentDidMount生命周期,而建立緩存的時候,父組件又會重新render。這樣就會出現(xiàn)死循環(huán)。所以,當(dāng)用以上方法時,切記不要加key或者加固定key,以免出現(xiàn)問題。
總結(jié)
以上是生活随笔為你收集整理的react循环setstate_react -- 关于兄弟组件触发更新的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis 启动_Redis介绍amp;
- 下一篇: cpu工作原理flash动画_cpu的基