Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use context api with react router v4?

I'm trying here on my application to do some tests with the new context API from React 16.3 but I can't understand why my redirect never works.

<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> 

I don't want to have my ContextB available for all the routes, just 2 and 3. How can I do this?

like image 687
vinicius sabadim Avatar asked May 03 '18 13:05

vinicius sabadim


People also ask

Is Redux better than context API?

Redux is much more powerful and provides a set of handy features that Context doesn't have. It's great for managing centralized state and handling API requests.

Is useContext same as context API?

The useContext is the React hook, used in context API to consume the context state or object. There are two options for getting the context object. We can get the context object from Context Consumer or useContext Hook. UseContext Hook is an exquisite, more excellent way to get the context object with less code.

Is useContext deprecated?

context is being shown as deprecated even though the official docs tells you to use it like this: class MyClass extends React. Component { componentDidMount() { let value = this. context; /* perform a side-effect at mount using the value of MyContext */ } componentDidUpdate() { let value = this.

Can I use both Redux and context API?

This can be achieved using Redux. With the release of React version 16.3, the new Context API was introduced as a solution to React prop drilling. As stated in React Documentation: Context provides a way to pass data through the component tree without having to pass props down manually at every level.


1 Answers

It looks like that <Switch> should only have <Route> and <Redirect > components as direct children. (source)

I suppose that's why your Redirect doesn't work as you use ContextB as a Switch child.

The simplest but repetitive solution could be to pass your ContextB as a child of each <Route> you want:

Note: These solutions suppose that you assigned the default value of your Context component like this: const MyContext = React.createContext(defaultValue);

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

You can even create a ContextRoute component for this:

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; 

And then use it as a Route:

<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> 

With this solution, you then use your context with render props in your nested Components:

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

But we can imagine much more solutions to this like HOC, passing context value directly to the route component props, etc...

like image 171
Nenu Avatar answered Sep 20 '22 16:09

Nenu