簡體   English   中英

更新動態創建的組件

[英]Update dynamic created components

情況

我有一個父組件,它呈現一些子組件。 子組件應顯示從父組件傳遞的信息。

上下文

與多人游戲的戰艦游戲:

父組件包含10x10到​​10x30按鈕(子組件)的字段。 如果按下按鈕,則具有按鈕位置的信號將被發射到api。 api決定按下的按鈕是否需要改變它的顏色。


問題

通過更新父級的狀態,如果動態創建子級,則不會更新子組件props。


解決方案嘗試

不要動態渲染Childs:

在我的情況下不可能

使用redux

我認為孩子是轉儲/表示組件,因為它只顯示信息。 在我的情況下,還有100-300個子組件。 Redux和React

使用refs

有100-300個兒童組件... 不要過度使用參考


我該怎么辦? 有沒有反模式的解決方案?

現行守則

 class Parent extends React.Component { constructor(props) { super(props); this.state={ foo: 'BAR' } this.child=undefined; } componentWillMount(){ this.child=<Child foo={this.state.foo}/> } componentDidMount(){ var that=this setTimeout(function(){ that.setState({ //it is just here for demonstration foo: 'FOO' }) }, 1000); } render() { return ( <div> Is: {this.child} Not Dynamic created: <Child foo={this.state.foo}/> Actual: <p>{this.state.foo}</p> </div> ); } } class Child extends React.Component { render() { return ( <p>{this.props.foo}</p> ); } } ReactDOM.render(<Parent />, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

代碼來自@RaghavGarg和@Clinton Blackburn

 class Parent extends React.Component { constructor(props) { super(props); this.state={ foo: 'BAR' } this.child=undefined; } componentDidMount(){ var that=this setTimeout(function(){ that.setState({ //it is just here for demonstration foo: 'FOO' }) }, 1000); } renderChild(){ return <Child foo={this.state.foo} /> } render() { const child=this.renderChild() return ( <div> Is: {child} Not Dynamic created: <Child foo={this.state.foo}/> Actual: <p>{this.state.foo}</p> </div> ); } } class Child extends React.Component { render() { return ( <p>{this.props.foo}</p> ); } } ReactDOM.render(<Parent />, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='app'/> 

就像@Clinton所說的那樣, componentWillMount只會調用一次。 因此,您實際上是在啟動this.child變量,但只更新狀態,還需要更新變量的值。

因為您只是制作動態組件並將它們保存在類實例中(如this.child )。 我建議你在componentWillUpdate執行相同的任務。 因此,無論何時狀態發生變化,它都會反映在您的因變量中。 但請確保不要在此生命周期方法中使用setState

在接收新的道具或狀態時,在渲染之前調用componentWillUpdate() 使用此作為在更新發生之前執行准備的機會。

另外,請考慮使用構造函數來啟動狀態,而不是在componentWillMount使用setState

在安裝發生之前調用componentWillMount() 它在render()之前調用,因此在此方法中同步調用setState()不會觸發額外的渲染。 通常,我們建議使用constructor()來初始化狀態。

參考:

https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate https://reactjs.org/docs/react-component.html#unsafe_componentwillmount

添加上下文后更新

所以現在,我假設您將在維持每個框(子組件)狀態的狀態下擁有DS(可能是對象或嵌套數組)。 你可以遍歷它並為它們中的每一個提供一個唯一的key (可能像{row}-{col} ),現在你只需要更新狀態以反映特定子項的變化。

注意:對每個子項使用唯一鍵將啟用react內部優化重新呈現,並且不會重新呈現子項(使用唯一鍵),這不會更改。 請參閱以下代碼以供參考。

this.state = {
  boxes: {
    1: { 
      1:{ status: true, /* more data */ },
      2:{ status: true, /* more data */ },
    },
    2: { 
      1:{ status: true, /* more data */ },
      2:{ status: true, /* more data */ },
    },
    3: { 
      1:{ status: true, /* more data */ },
      2:{ status: true, /* more data */ },
    },
    4: { 
      1:{ status: true, /* more data */ },
      2:{ status: true, /* more data */ },
    }
  }
};

// this will create a 4x2 box, now you will render using above object

// ...somewhere in your render method
{
  Object.keys(this.state.boxes).map(row => (
    <div key={`row-${row}`} className="row">
      {
        Object.keys(this.state.boxes[row]).map(column => (
          <Child 
            key={`box-${row}x${column}`} 
            data={this.state.boxes[row][column]} 
          />
        ))
      }
    </div>
  ))
}

現在,每當您將2x1框的status更改為false ,react將僅使用密鑰box-2x1重新呈現子項。

OP評論后更新

應該使用shouldComponentUpdate來決定是否要在狀態更改時更新組件。 它是React組件的生命周期方法。 默認情況下,它返回true ,但您可以根據條件返回false基礎,以便不更新組件。 這肯定有助於保持良好的表現。

參考: React:父組件重新呈現所有子項,甚至是那些在狀態更改時沒有更改的子項

componentWillMount僅在將父組件插入DOM時調用一次。 可能不是您想要創建安裝后需要更改的子組件的位置。 請參閱https://reactjs.org/docs/react-component.html#the-component-lifecycle上的組件生命周期。

最簡單的解決方案是在render()方法中創建子組件。 更新父組件時將重新創建子組件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM