React router dom v6 Auth

Viewed 1756

I am having the hardest time trying to understand the react-router Auth. I have read the (horrible) documentation numerous times and i have followed MANY tutorials on the web. Not a single one has worked. The example provided by React is written in typescript which makes it even harder to understand. Please help me figure this out.

They (React Dev Tutorial) use context and providers. But i cant seem to understand that either. IMO its very very convoluted unlike the rest of React-router.

When i run the login function from auth.js it seems to work and then it just resets the hook to false and never loads the next page. I feel like im so close but there is something wrong with the auth.js file?

app.js

function RequireAuth({children}) {
  let location = useLocation();
  const { authed } = UseAuth();

  console.log(authed);


  return authed ? children : <Navigate to="/" state={{from: location}}/>;
}
<Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <BrowserRouter location={history.location} navigator={history}>
          <AuthProvider>
          <Routes>

          <Route index element={<Login setData={setData} type={type}/>} />


              <Route path="adminDashboard" element={
                <RequireAuth redirectTo="/"> 
                  <AdminDashboard />
                </RequireAuth>
                } 
              />
              

              <Route path="userDashboard" element={
                <RequireAuth redirectTo="/"> 
                  <UserDashboard />
                </RequireAuth>
              } />
           </Routes>
          </AuthProvider>
        </BrowserRouter>
      </PersistGate>
    </Provider>

login.js

  const auth = UseAuth();
  auth.login();

auth.js the auth.js file came from a seperate tutorial

import * as React from "react";

const authContext = React.createContext({
  authed: false,
  login: () => {},
  logout: () => {}
});

export default function UseAuth() {
  return React.useContext(authContext);
}

export function AuthProvider({ children }) {
  const [authed, setAuthed] = React.useState(false);
  let auth = UseAuth();

  const login = () => setAuthed(true, console.log(authed));
  const logout = () => setAuthed(false);

  let value = { authed, login, logout };


  return (
    <authContext.Provider value={value}>
      {children}
    </authContext.Provider>
  );
}
2 Answers

the useAuth returns 3 things authed, login() and logout(). so when u are calling let auth = useAuth(), auth is an object that contains all three of those.

Try deconstructing to useAuth returns like

const { authed, login, logout } = useAuth()

and use the authed instead

You do appear to be close. The useAuth hook returns an object { authed, login, logout }, but you are naming the entire object auth in your RequireAuth wrapper component and using it as the condition. It's a defined object so it will always be truthy. It looks like you just need to access the authed property from that object to know if a user has authenticated or not.

function RequireAuth({ children }) {
  const location = useLocation();
  const { authed } = useAuth();
  return auth ? children : <Navigate to="/" state={{from: location}}/>;
}

You also seem to have mixed up your auth context a bit. The state should reside in the context provider while the useAuth hook returns the provided value.

const authContext = React.createContext({
  authed: false,
  login: () => {},
  logout: () => {}
});

export default function useAuth() {
  return React.useContext(authContext);
}

export function AuthProvider({ children }) {
  const [authed, setAuthed] = React.useState(false);

  const login = () => setAuthed(true);
  const logout = () => setAuthed(false);

  return (
    <authContext.Provider value={{ authed, login, logout }}>
      {children}
    </authContext.Provider>
  );
}
Related