[英]Updating child props from parent state in 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回调时,组件永远不会收到更新的配方数组。
我该如何根据App中的更新状态来更新道具?
还是我以错误的方式来处理整件事?
我认为您的方法并不是真的很像反应,并且您至少有两个可以改进的概念。
首先,我肯定会使用react-router在React.js中的页面/组件之间实现任何复杂的导航。 自己实施更复杂且容易出错。 react-router允许您轻松地将组件分配给不同的路由。
其次,我认为你应该几乎从不存储在上下文中的东西this
直接。 基本上是因为它会导致像您这样的错误:根本没有意识到appStates
根本没有改变。 React的状态是一个很棒的工具(有时必须用Redux等其他工具替换/补充)来存储应用程序的状态。
在以状态形式存储应该在Component中呈现的内容的情况下,您可能应该在构造函数中初始化的状态下使用简单标志来补充react-router功能,以使您知道应该在render函数中返回什么。
这是一个示例,显示了如何告诉组件仅使用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>
您的构造方法仅在组件安装时执行,此时配方为空,并将该空数组传递给appStates。 本质上,appStates永远不会改变。
我建议做的是将构造函数中的所有组件代码推送到render函数内部。 反应的好处在于您可以以很少的成本完全重新渲染所有内容。 React将进行比较DOM差异的艰苦工作,并且仅重新呈现最小差异。
我同意@Ezra Chang。 我认为可以仅使用状态和javascript传播函数来调整代码,以将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];
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.