I have written AuthContext.js in a seprate file like bellow
export const AuthContext = createContext({
isLoggedIn: false,
login: () => {},
logout: () => {},
});
const AuthContextProvider = (props) => {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const loginHandler = useCallback(() => {
setIsLoggedIn(true);
}, []);
const logoutHandler = useCallback(() => {
setIsLoggedIn(false);
}, []);
const initialValue = {
isLoggedIn: isLoggedIn,
login: loginHandler,
logout: logoutHandler,
};
return (
<AuthContext.Provider value={initialValue}>
{props.children}
</AuthContext.Provider>;
);
};
export default AuthContextProvider;
Then I import them manually in App.js
I recognized that when do I login, App.js
never re-render even the value of isLoggedIn
changed.
Result in routes
variable never gotten new values, components will not change as well.
The App.js file
const App = () => {
const authCtx = useContext(AuthContext);
const { isLoggedIn } = authCtx;
let routes;
if (isLoggedIn) {
routes = (
<Switch>
<Route path="/" exact>
<Users />
</Route>
<Route path="/places/new" exact>
<NewPlace />
</Route>
<Route path="/:userId/places" exact>
<UserPlaces />
</Route>
<Route path="/places/:placeId">
<UpdatePlace />
</Route>
<Redirect to="/" />
</Switch>
);
}
else {
routes = (
<Switch>
<Route path="/" exact>
<Users />
</Route>
<Route path="/:userId/places" exact>
<UserPlaces />
</Route>
<Route path="/signin" exact>
<SignIn />
</Route>
<Route path="/signup" exact>
<Signup />
</Route>
<Redirect to="/signin" />
</Switch>
);
}
return (
<AuthContextProvider>
<BrowserRouter>
<MainNavigation />
<main>{routes}</main>
</BrowserRouter>
</AuthContextProvider>
);
};
export default App;
What is my mistake in this case.
CodePudding user response:
If App
is the component rendering the AuthContextProvider
component then it can't access the Context value it provides. The AuthContextProvider
must be rendered higher in the ReactTree in order for App
to be able to access the Context value. Current App
is receiving the default value that was passed to React.createContext
.
export const AuthContext = createContext({
isLoggedIn: false,
login: () => {},
logout: () => {},
});
The default value is used when there is not any Context provider higher in the ReactTree.
Move AuthContextProvider
to be higher in the ReactTree, i.e. wrap App
.
App
const App = () => {
const { isLoggedIn } = useContext(AuthContext);
let routes;
if (isLoggedIn) {
routes = (
<Switch>
<Route path="/" exact>
<Users />
</Route>
<Route path="/places/new" exact>
<NewPlace />
</Route>
<Route path="/:userId/places" exact>
<UserPlaces />
</Route>
<Route path="/places/:placeId">
<UpdatePlace />
</Route>
<Redirect to="/" />
</Switch>
);
}
else {
routes = (
<Switch>
<Route path="/" exact>
<Users />
</Route>
<Route path="/:userId/places" exact>
<UserPlaces />
</Route>
<Route path="/signin" exact>
<SignIn />
</Route>
<Route path="/signup" exact>
<Signup />
</Route>
<Redirect to="/signin" />
</Switch>
);
}
return (
<>
<MainNavigation />
<main>{routes}</main>
</>
);
};
export default App;
<AuthContextProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</AuthContextProvider>