Home > Back-end >  Write AuthContext.js in a separate file
Write AuthContext.js in a separate file

Time:01-11

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