我想知道我有什么样的解决方案来解决以下问题:
我不使用任何州管理库。我“只使用”React。
全局应用程序状态存储在组件<MyFoodApp/>
中。它包含一系列 restaurant 对象。
组件RestaurantPage
用于显示餐馆的详细信息,并允许创建新评论。
此时我被卡住了,因为我需要更新以restaurant
状态存储的特定 <MyFoodApp />
对象,以便添加此提交的评论
我曾经通过作为道具传递到子组件的函数更新状态,但在这种情况下我不能,因为MyFoodApp
不是RestaurantPage
的父级。
我是否必须设置Redux
来解决此问题,还是有任何解决方法?
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom';
import EasyFoodApp from './js/components/EasyFoodApp';
import RestaurantPage from './js/components/RestaurantPage';
import NotFound from './js/components/NotFound';
class Root extends React.Component {
render() {
return (
<Router>
<div className="router">
<Switch>
<Route exact path="/" component={MyFoodApp} />
<Route
path="/restaurant/:slug"
component={RestaurantPage}
/>
<Route render={() => <NotFound />} />
</Switch>
</div>
</Router>
);
}
}
ReactDOM.render(<Root />, document.getElementById('root'));
答案 0 :(得分:3)
在没有实际使用状态管理库的情况下,您可以解决几个问题,
首先:提升状态,
这是最正确的解决方案,因为您的组件和路由没有高度嵌套,并且数据需要由彼此兄弟的组件处理,
class Root extends React.Component {
state = {
restaurant: [] // store the restaurant data here instead of MyFoodApp
}
restaurantUpdater = () => {
//utility function to update state
}
render() {
return (
<Router>
<div className="router">
<Switch>
<Route exact path="/" render={props => <MyFoodApp {...props} restaurant={this.state.data} />} restaurantUpdater={this.restaurantUpdater} />
<Route
path="/restaurant/:slug"
render={props => <RestaurantPage {...props} restaurant={this.state.data} />} restaurantUpdater={this.restaurantUpdater} />
/>
<Route render={(props) => <NotFound {...props}/>} />
</Switch>
</div>
</Router>
);
}
}
第二:使用Context API
当您的数据需要传递到不同级别的组件时,您可以使用Context
。正如反应文档所说
配置上下文的使用不要仅使用上下文来避免将道具向下移动几级。棒 在许多组件中需要访问相同数据的情况 在多个层面。
export const RestaurantContext = React.createContext({
restaurant: [],
restaurantUpdater: () => {},
});
class RestaurantProvider extends React.Component {
state = {
restaurant: [] // store the restaurant data here instead of MyFoodApp
}
restaurantUpdater = () => {
//utility function to update state
}
render() {
<RestaurantContext.Provider value={this.state}>
{this.props.children}
</RestaurantContext.Provider>
}
}
然后为消费者创建一个HOC
import RestaurantContext from 'path/to/restaurantContext'
const withContext = (Component) => {
return (props) => <RestaurantContext.Consumer>
{(restaurant, restaurantUpdater) => <Component {...props} restaurant={restaurant} restaurantUpdater={restaurantUpdater} />}
</RestaurantContext.Consumer>
}
现在您可以在
这样的组件中使用它export default withContext(MyFoodApp);
并且您的FoodApp可以使用来自
等道具的restaurant
和restaurantUpdater
const { restaurant, restaurantUpdater} = this.props
同样可以在其他组件中使用它
答案 1 :(得分:0)
您的答案的解决方案是创建子路由,以便从 MyFoodApp 组件到 RestaurantPage 组件进行子路由。
内部 MyFoodApp 的渲染方法*注意:不要在路线内再次使用开关
<Switch>
<Route exact path="/restaurant" render={() => <RestaurantPage pages={this.arrayOfRestaurant}/>
</Switch>
我希望它会有所帮助
答案 2 :(得分:0)
如果其中一个方案符合您的组件排列,则可以在没有redux的情况下管理数据:
但是这两种关系都不能满足您对组件的安排,因为这两个组件是新的根组件。
当组件无法在任何类型的父子关系之间进行通信时,documentation建议设置全局事件系统。