Home > Blockchain >  useNavigate() function not always working?
useNavigate() function not always working?

Time:12-21

I'm building a MERN Web App and I'm going through an issue: when I login with an existing account, after calling an API to the backend and handling the request, it returns the user properties and the JWT Token, I save it and then (using navigate function) I redirect the User to the homepage. It works fine but it doesn't when i relaod the page. I mean in the first load of the page the login works fine and so does the navigate function, but when I reload the page and enter the login data, it does login but does not redirect me to the homepage. I hope it is understandable! This is the snippet of the code which makes the API call and then the redirect:

Login.js

const handleSubmit = async (event) => {
    event.preventDefault()
    try {
            const res = await axios.post(WEB_URL   `/login`, { email, password })
        // console.log(res.data);
        const { token } = res.data.token;
        localStorage.setItem('jwt', token);
        // console.log('logged as', res.data.user.name);
        navigate("/");
    }
    catch (error) {
        console.log(error);
        navigate("/login");
    }
};

App.js

    const PrivateRoute = () => {
        const token = localStorage.getItem('jwt');
        return !!token;
    };

    function App() {
        return (
            <Router>
                <Navbar />
                <Routes>
                    <Route path="/" element={PrivateRoute() ? <Home /> : <Navigate replace to="/login" />} />
                    <Route path="/login" element={<Login />} />
                    <Route path="/register" element={<Register />} />
                </Routes>
            </Router>
        );
    }

CodePudding user response:

Issue

The issue here is that when App renders it calls PrivateRoute the function and it correctly returns false since no user is logged in and the <Navigate> component is rendered.

The router is correctly navigated to "/login" and the Login component is rendered and the user authenticates and is navigated back to "/". Because no state or props or parent component to App was updated the App component doesn't rerender and doesn't re-check the token in localStorage. This means the <Navigate> component is still rendered and the user is bounced back to "/login".

Solution

Make PrivateRoute an actual React component so the component is rendered/rerendered when the route changes, and so it can recheck the token in localStorage.

Example:

import { Navigate, Outlet } from 'react-router-dom';

const PrivateRoute = () => {
  const token = localStorage.getItem("jwt");
  return !!token ? <Outlet /> : <Navigate replace to="/login" />;
};

Render PrivateRoute on a layout route that renders the home page.

<Routes>
  <Route element={<PrivateRoute />}>
    <Route path="/" element={<Home />} />
  </Route>
  <Route path="/login" element={<Login />} />
</Routes>

Edit usenavigate-function-not-always-working

  • Related