2017-01-24 108 views
0

我在嘗試瞭解如何使用不同的「頁面」或「視圖」構建ReactJS應用程序。在ReactJS中更新父母狀態的子道具

我有以下組件作爲我的基本應用程序,我在React狀態中使用currentState屬性來切換視圖中哪些組件處於活動狀態。

class App extends React.Component { 

    constructor(props) { 
     super(props); 
     this.state = {currentState: 'Loading', recipes: []}; 
     this.appStates = { 
      'Loading': <Loading/>, 
      'Home': <RecipeList recipes={this.state.recipes}/> 
     } 
    } 

    dataLoaded(data) { 
     this.setState({ 
      recipes: data, 
      currentState: 'Home' 
     }); 
    } 

    componentDidMount() { 

     // AJAX Code that retrieves recipes from server and then calls dataLoaded 
    } 

    render() { 
     return this.appStates[this.state.currentState]; 
    } 
} 

哪個工作,但是當dataLoaded回調被觸發時,組件從不接收更新的配方數組。

如何根據應用程序中更新的狀態更新其道具?

或者我以錯誤的方式接近這件事?

+0

我認爲正在發生的事情是因爲「家」組件在構造函數中被定義,並且您將它的配方設置到數組中,當您更新配方數組時,您不會將元素推送到現有數組上,而是將新數組設置爲該變量,因此組件從不更新爲新數據。 – dule

回答

0

我推薦做的是將構造函數中的所有組件代碼推送到render函數中。反應的美妙之處在於你可以以很低的成本完全重新渲染所有東西。 React將做比較DOM差異的艱鉅工作,並只重新渲染最小差異。

1

您的構造函數方法僅在組件掛載時執行,此時食譜爲空,並將該空數組傳遞給appStates。實質上,appState從不改變。

2

我認爲你的見解並不是真正的反應,而且你至少有一些可以改進的概念。

首先,我肯定會使用react-router來實現React.js中頁面/組件之間的任何複雜導航。自己實現它更復雜且容易出錯。 react-router將允許您輕鬆地將組件分配給不同的路由。

其次,我認爲你應該幾乎從不直接在上下文this中存儲東西。基本上,因爲它導致像你這樣的錯誤:沒有意識到appStates根本沒有改變。 React的狀態是一個很好的工具(它有時必須替換爲Redux等其他工具),以存儲應用程序的狀態。

在存儲應該在組件中呈現的內容的情況下,您應該在構造函數中初始化的狀態下用簡單的標誌補充反應路由器的功能,以便讓您知道應該返回哪些內容渲染功能。

下面是一個示例,顯示如何通過使用React狀態來指示組件在加載和加載之間動態更改其視圖。當然,你可以重新創建一個非常類似的行爲,在componentDidMount中進行AJAX調用,並在完成而不是使用按鈕時更改狀態以停止加載。

class App extends React.Component { 
 

 
    constructor(props) { 
 
     super(props); 
 
     this.state = {loading: true}; 
 
     this.stopLoading = this.stopLoading.bind(this); 
 
    } 
 

 
    stopLoading() { 
 
     this.setState({ 
 
      loading: false, 
 
     }); 
 
    } 
 

 
    render() { 
 
     let view=<div><h1>loading</h1><button onClick={this.stopLoading}>FINISH</button></div>; 
 
     if(!this.state.loading){ 
 
      view=<h1>loaded</h1>; 
 
     } 
 
     return <div>{view}</div>; 
 
    } 
 
} 
 

 
ReactDOM.render(
 
    <App />, 
 
    document.getElementById('container') 
 
);
<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="container"></div>

0

我@Ezra昌同意。我覺得代碼可以調整,只需使用狀態和javascript spread function到App道具傳遞給孩子RecipeList:

class App extends React.Component { 

    constructor(props) { 
     super(props); 
     this.state = {currentState: 'Loading', recipes: [],'Loading': <Loading/>, 
     'Home': <RecipeList recipes={this.state.recipes} {...this.props}/>}; 
    } 

    //I assume you want to pass the props of this App component and the data from the back-end as props to RecipeList. 
    dataLoaded = (data) => { 
     this.setState({ 
      recipes: data, 
      currentState: 'Home', 
      'Loading': <Loading/>, 
      'Home': <RecipeList recipes={data} {...this.props}/> 
     }); 
    } 

    componentDidMount() { 
     // AJAX Code that retrieves recipes from server and then calls dataLoaded 
    } 

    render() { 
     return this.state[this.state.currentState]; 
    } 
}