如何使用context api with react router v4?

时间:2018-05-03 13:10:19

标签: reactjs react-router

我正在尝试使用React 16.3中的新上下文API对我的应用程序进行一些测试,但我无法理解为什么我的重定向永远不会起作用。

<ContextA>
  <Switch>
    <Route exact path='/route1' component={ Component1 } />
    <ContextB>
      <Route exact path='/route2' component={ Component2 } />
      <Route exact path='/route3' component={ Component3 } />
    </ContextB>
    <Redirect from='/' to='/route1' />
  </Switch>
</ContextA>

我不希望我的ContextB可用于所有路由,只有2和3.我该怎么做?

5 个答案:

答案 0 :(得分:9)

警告他人,接受的答案并非真正有效,正如您对原始(无效)概念所期望的那样:

// This comes from the original question (doesn't work as-is!)
<ContextA>
  <Switch>
    <Route exact path='/route1' component={ Component1 } />
      <ContextB>
        <Route exact path='/route2' component={ Component2 } />
        <Route exact path='/route3' component={ Component3 } />
      </ContextB>
      <Redirect from='/' to='/route1' />
   </Switch>
</ContextA>

在这里,/route2/route3正在共享上下文,期望应该是:

  1. 在路由转换之间保持状态。
  2. 如果Component2Component3更新了上下文,则更改应反映回对方。

以上都不是公认的解决方案。

答案 1 :(得分:6)

看起来<Switch>应该只有<Route><Redirect >组件作为直接子项。 (source

我认为这就是为什么Redirect无效,因为您使用ContextB作为Switch孩子。

最简单但重复的解决方案可能是将ContextB作为您想要的每个<Route>的孩子传递:

  

注意:这些解决方案假设您为此分配了Context组件的默认值,如下所示:const MyContext = React.createContext(defaultValue);

<Route exact path='/route2'>
  <ContextB.Provider>
    <Component1 />
  </ContextB.Provider>
</Route>

您甚至可以为此创建ContextRoute组件:

import React from 'react';
import { Route } from 'react-router-dom';

const ContextRoute = ({ contextComponent, component, ...rest }) => {
  const { Provider } = contextComponent;
  const Component = component;

  return (
    <Route {...rest}>
      <Provider>
        <Component />
      </Provider>
    </Route>
  );
};

export default ContextRoute;

然后将其用作路线:

<ContextA>
  <Switch>
    <Route exact path='/route1' component={ Component1 } />
    <ContextRoute exact path='/route2' contextComponent={ContextB} component={ Component2 } />
    <ContextRoute exact path='/route3' contextComponent={ContextB} component={ Component3 } />
    <Redirect from='/' to='/route1' />
  </Switch>
</ContextA>

使用此解决方案,您可以在嵌套的组件中使用渲染道具的上下文:

return (
  <ContextB.Consumer>
    {value => <div>{value}</div>}
  </ContextB.Consumer>
);

但我们可以想象更多的解决方案,比如 HOC ,将上下文值直接传递给路径组件道具等......

答案 2 :(得分:1)

感谢您的帮助,我在商店环境中使用了它,并且可以使用! (createContext和useReducer)

import React, {createContext, useReducer} from "react";
import Reducer from './reducer.js'

const initialState = {
    /* */
};
const Store = ({children}) => {
    const [state, dispatch] = useReducer(Reducer, initialState);

    return (
        <Context.Provider value={[state, dispatch]}>
            {children}
        </Context.Provider>
    )
};

export const Context = createContext(initialState);
export default Store;

/ *在App.js * /

const App = () => {

    return (
    <BrowserRouter>
            <Switch>
            <Route exact path="/" render={ (props)=> <Store> <Home {...props} /> </Store> } />
            <Route exact path="/about" render={ (props)=> <Store> <About {...props} /> </Store> } />
            <Route exact path="/login" render={ (props)=> <Store> <Login {...props} /> </Store> } />
            </Switch>

    </BrowserRouter>
    );
};

答案 3 :(得分:0)

在Route中使用render方法。这将解决您的问题,就像我在应用程序中所做的一样。

<Route path="/" render={ (props)=> <ContextB> <Component2 {...props} /> </ContextB> }

答案 4 :(得分:0)

简单的解决方案:

Select Col1, Col2, Col3, Col4, Col5 from Table1
Union
Select Col1, Col2, Col3, Null as Col4, Null as Col5 from Table2````