Search code examples
javascriptreactjsreact-routerreact-router-domreact-functional-component

history.push is not working after login function


I am trying to use history.push() after setting the token. Somehow the page doesn't redirect to a new path. I have used useHistory feature for accessing history. Once I reload the page it is redirecting to home. I tried other sort of hacks but unable to find solution. Please help.

App.js

function App() {
  const [isAuthenticated, setAuthenticated] = useState(false);
  useEffect(()=>{
    if(cookie.get('authorization')){
      setAuthenticated(true);
    }
    else{
      setAuthenticated(false);
    }
  },[])
  return (
    <Router>
      <Switch>
        <Route exact path="/">
          {isAuthenticated?<Redirect to="/home"/>:<Login />}
        </Route>
        <PrivateRoute exact path="/user/:id" component={UserDetail} auth={isAuthenticated} />
        <PrivateRoute exact path="/createuser" component={CreateUser} auth={isAuthenticated} />
        <PrivateRoute exact path="/home" component={ListUser} auth={isAuthenticated} />
      </Switch>
    </Router>
  );
}

export default App;

login.js

import React, { useEffect, useState } from 'react';
import {useHistory} from 'react-router-dom';

function Login() {
    const history = useHistory();
    const loginUser = (body) => {
        SetLoader(true);
        fetch('/api/v2/users/tokens', {
            method: 'POST',
            body: JSON.stringify(body),
            headers: {
                'Content-Type': 'application/json',
            }
        })
            .then(response => {
                SetLoader(false);
                if (response.status == 200) {
                    SetError(false);   
                    cookie.set('authorization',response.headers.map.authorization,{path:'/'});
                    history.push('/');
                }
                else {
                    SetError(true);
                    StoreResponse(JSON.parse(response._bodyInit).message);
                }
            })
            .catch((error) => {
                console.error('Error:', error);
            });
    }
}

export default Login;

Solution

  • I don't see where history is defined in Login component. Also, you set the cookie, but isAuthenticated is only ever set when App component mounts, it is never updated later.

    You could pass a callback to Login to update the state in App and let the redirect happen naturally when App rerenders and rerenders the routes with the re-enclosed isAuthenticated state. The Switch also already attempts to match and render routes exclusively, so order your paths most specific to least specific and you won't need to add the exact prop to every route.

    App

    function App() {
      const [isAuthenticated, setAuthenticated] = useState(false);
    
      useEffect(() => {
        if (cookie.get("authorization")) {
          setAuthenticated(true);
        } else {
          setAuthenticated(false);
        }
      }, []);
    
      return (
        <Router>
          <Switch>
            <PrivateRoute
              path="/user/:id"
              component={UserDetail}
              auth={isAuthenticated}
            />
            <PrivateRoute
              path="/createuser"
              component={CreateUser}
              auth={isAuthenticated}
            />
            <PrivateRoute
              path="/home"
              component={ListUser}
              auth={isAuthenticated}
            />
            <Route path="/">
              {isAuthenticated ? (
                <Redirect to="/home" />
              ) : (
                <Login setAuthenticated={setAuthenticated} /> // <-- pass callback
              )}
            </Route>
          </Switch>
        </Router>
      );
    }
    

    Login

    function Login({ setAuthenticated }) { // <-- destructure prop
      const loginUser = (body) => {
        SetLoader(true);
        fetch("/api/v2/users/tokens", {
          method: "POST",
          body: JSON.stringify(body),
          headers: {
            "Content-Type": "application/json"
          }
        })
          .then((response) => {
            if (response.status == 200) {
              SetError(false);
              cookie.set("authorization", response.headers.map.authorization, {
                path: "/"
              });
              setAuthenticated(true); // <-- set authenticated
            } else {
              SetError(true);
              StoreResponse(JSON.parse(response._bodyInit).message);
            }
          })
          .catch((error) => {
            console.error("Error:", error);
          })
          .finally(() => {
            SetLoader(false); // <-- set loading false in finally block
          });
      };
    
      ...
    }