5

I'm using react-router-dom v6 and I'm accessing the from value from the location object and it gives the pathname but when executing navigate(from,{replace:true}) it does not work.

const navigate = useNavigate();
const { state } = useLocation();
const from = state ? state.from.pathname : '/';
const [isDone, setIsDone] = useState(false);
  useEffect(() => {
    if (isDone) {
      navigate(from, { replace: true }); //not working
    }
  }, [isDone]);
const Submit = async (e) => {
    e.preventDefault();
    let data = { email, password };

    if (!email || !password) {
      setMessage('Please Enter All Fields');
    } else {
      setLoading(true);
      return await axios
        .post('/signin', data)
        .then((res) => {
          if (res.data.message === 'Invalid Credentials') {
            setMessage('Invalid Credentials');
          }
          if (res.data.message === 'Logged In') {
            setIsDone(true);
          }
        })
        .catch((err) => {
          console.log(err);
        })
        .finally(() => {
          setLoading(false);
        });
    }
Haree Prasad
  • 103
  • 1
  • 2
  • 8

4 Answers4

1

I think the issue is with '/', remove it from the URL and try.

navigate(from.replace('/', '') , { replace: true });
Rahul Sharma
  • 9,534
  • 1
  • 15
  • 37
1

After fixing your CSB I see the redirect working. The issue is that the auth value in App doesn't change because your login flow doesn't set the logged_in_status value stored in localStorage. The result is that the user is bounced right back to the "/signin" route.

You should also be serializing/deserializing the data you save/access to/from localStorage.

App

const auth = JSON.parse(localStorage.getItem('logged_in_status'));

...

useEffect(() => {
  const checkAuthStatus = async () => {
    return await axios.get("/loginstatus").then((res) => {
      if (res.data.message === "No Token") {
        localStorage.setItem("logged_in_status", JSON.stringify(false));
      }
      if (res.data.message === "Invalid Token") {
        localStorage.setItem("logged_in_status", JSON.stringify(false));
      }
      if (res.data.message === "Valid Token") {
        localStorage.setItem("logged_in_status", JSON.stringify(true));
      }
    });
  };
  checkAuthStatus();
});

Use a boolean expression for checking the auth value in your route wrappers.

const PublicRoute = () => {
  if (auth) {
    return <Navigate to="/" replace={true} state={{ from: location }} />;
  }
  return <Outlet />;
};

const PrivateRoute = () => {
  if (!auth) {
    return (
      <Navigate to="/signin" replace={true} state={{ from: location }} />
    );
  }

  return <Outlet />;
};

Signin

Here you just need to set a true "logged_in_status" into localStorage upon successful authentication. There's also no real need I see for setting the done state; you can simply issue the imperative redirect when authenticated.

const Submit = async (e) => {
  e.preventDefault();
  let data = { email, password };

  if (!email || !password) {
    setMessage("Please Enter All Fields");
  } else {
    setLoading(true);
    return await axios
      .post("/signin", data)
      .then((res) => {
        if (res.data.message === "Invalid Credentials") {
          setMessage("Invalid Credentials");
        }
        if (res.data.message === "Logged In") {
          localStorage.setItem("logged_in_status", JSON.stringify(true)); // <-- set localStorage
          navigate(from, { replace: true }); // <-- redirect
        }
      })
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        setLoading(false);
      });
  }
};

Edit usenavigate-not-working-react-router-dom-v6

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

I just simply use:

import { useNavigate } from 'react-router-dom';
...
const navigate = useNavigate();
...
<Button onClick={() => navigate('../login', { replace: true })}>LogOut</Button>

So, I added ../ before the route and the replace: true.

Reference:- React Router v6...

Deepak Singh
  • 749
  • 4
  • 16
0

in my case navigate is not work in Link tag

<Link onClick={()=>{navigate("/login")}}>
  <i className="fa fa-user-o  login-icon" aria-hidden="true"></i>
</Link>

this is work for me.

<span onClick={()=>{navigate("/login")}}>
  <i className="fa fa-user-o  login-icon" aria-hidden="true"></i>
</span>
UdevApp
  • 31
  • 5