如何在React Router v4路由之间共享应用程序状态

Adr*_*n G 2 javascript reactjs react-router-v4

我想知道我必须采用哪种解决方案来解决以下问题:

我不使用任何状态管理库。我“只使用” React。

全局应用程序状态存储在组件中<MyFoodApp/>。它包含一组餐厅对象。

该组件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'));
Run Code Online (Sandbox Code Playgroud)

我发现老相关的职位像这一个这一个,但有可能来处理这个问题的新途径。

Shu*_*tri 7

在不实际使用状态管理库的情况下,有两种解决方法可以解决您的问题,

第一:提升状态,

这是最正确的解决方案,因为您的组件和路由不是高度嵌套的,并且数据需要由彼此兄弟的组件处理,

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>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

第二:利用上下文API

您可以利用Context何时需要将数据向下传递到不同级别的组件。正如反应文档所说

不要仅仅为了避免将道具向下传递几个级别而使用上下文。坚持需要在多个级别的多个组件中访问相同数据的情况。

您可以使用React 16.3 context API like 配置上下文的使用

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>
   }
}
Run Code Online (Sandbox Code Playgroud)

然后为消费者创建HOC

import RestaurantContext from 'path/to/restaurantContext'
const withContext = (Component) => {
    return (props) => <RestaurantContext.Consumer>
        {(restaurant, restaurantUpdater) => <Component {...props} restaurant={restaurant} restaurantUpdater={restaurantUpdater} />}
    </RestaurantContext.Consumer>
}
Run Code Online (Sandbox Code Playgroud)

现在您可以在类似

export default withContext(MyFoodApp);
Run Code Online (Sandbox Code Playgroud)

和你的FoodApp可以使用restaurantrestaurantUpdater从像道具

const { restaurant, restaurantUpdater} = this.props
Run Code Online (Sandbox Code Playgroud)

同样,您可以在其他组件中使用它