Here I am using react-router and using conditionals for multiple routes. I am using context to store my state. I want to load my data from localStorage to the state before my App.js is loaded as based on that it tells on which routes should I navigate to.
userContext.js
import React, { useState, createContext, useEffect } from "react";
export const userContext = createContext();
export const UserProvider = (props) => {
const [user, setUser] = useState(null);
const loadFromLocalStorage = () => {
try {
const serializedState = localStorage.getItem("state");
if (serializedState == null) return undefined;
return JSON.parse(serializedState);
} catch (err) {
console.log(err);
return null;
}
};
useEffect(() => {
const state = loadFromLocalStorage();
console.log("state: ", state);
setUser(state);
}, []);
return (
<userContext.Provider value={[user, setUser]}>
{props.children}
</userContext.Provider>
);
};
export default userContext;
App.js
import React, { useContext, useEffect } from "react";
import { Switch, Route, Redirect } from "react-router";
import userContext from "./context/userContext";
const App = () => {
var routes = null;
const [user, setUser] = useContext(userContext);
console.log("app: ", user);
console.log(routes);
if (user == null) {
routes = (
<div>
<Switch>
<Route path="/login" component={SignUp} />
<Redirect to="/login"></Redirect>
</Switch>
</div>
);
} else {
routes = (
<div>
<Switch>
<Route exact path="/news" component={NewsList} />
<Redirect to="/news"></Redirect>
</Switch>
</div>
);
}
return <div className="App">{routes}</div>;
};
export default App;
CodePudding user response:
Inside your UserProvider, don't render the children until you've loaded data from localstorage. This will require some extra state, but nothing too bad, and this is a common pattern for asynchronous context/state:
export const UserProvider = (props) => {
const [isReady, setIsReady] = useState(false);
// other code removed for brevity
useEffect(() => {
const state = loadFromLocalStorage();
setIsReady(true);
}, [])
return (
<userContext.Provider value={[user, setUser]}>
{isReady ? props.children : null}
</userContext.Provider>
);
}