Looking through old tutorials it seems like React Router v5 had support for sharing state across different routes using the context API but I can't find anything on a similar usage for Router v6.
const [user, setUser] = useState(null);
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about/">About</Link>
</li>
</ul>
</nav>
<UserContext.Provider value={user,setUser}>
<Route path="/" exact component={Index} />
<Route path="/about/" component={About} />
</UserContext.Provider>
</div>
</Router>
);
and then you can access the state using the useContext
hook
const {value, setValue} = useContext(UserContext);
When attempting to use this implementation with v6 (exchanging the degraded v5 components for the new v6 ones) you will run into errors because you can only have <Route>
components as children in a router.
Is it possible to share state with a global context store across React Router V6 routes?
Below is my attempt at V6 implementation:
index.js
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById("root")
);
App.js
const [value, setValue] = useState("initial state");
return (
<>
<Header props={(key, setKey)} />
<DataContext.Provider value={(value, setValue)}>
<Route path="/" element={<Dashboard />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/configuration" element={<Configuration />} />
</DataContext.Provider>
</>
);
App.js different Approach
const [value, setValue] = useState("initial state");
return (
<DataContext.Provider value={(value, setValue)}>
<Header props={(key, setKey)} />
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/configuration" element={<Configuration />} />
</Routes>
</DataContext.Provider>
);
}
The issue with this solution is the state is still not updated globally when changed in one of the routes.
For example in /dashboard
if I change value using setValue
then it will reflect the changes in /dashboard
but if I navigate to /configuration
or refresh value
will have reverted to original value
, "initial state" in this case. (This is also the effect if I make a function in App.js
which will use setValue
and I pass the function to Provider instead)
I am sure that I could use React Redux to solve this problem but its really just one or two pieces of data that I need shared between routes - seems like overkill to implement all of the required redux boilerplate etc. and seems like a common use case that context should support.
Its simple you need to use Router
inside your DataProvider
.
// import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
<App />,
document.getElementById("root")
);
import { BrowserRouter as Router } from "react-router-dom";
// .....
// .....
// .....
const [value, setValue] = useState("initial state");
return (
<DataContext.Provider value={(value, setValue)}>
<Header props={(key, setKey)} />
<Router>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/configuration" element={<Configuration />} />
</Routes>
</Router>
</DataContext.Provider>
);
}
Also make sure you are using the Link
of router to navigate to different pages. Using any other thing 'a' tag, etc. that refreshes the page will reset the context
.