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);
        });
    }
9
  • Please clarify what "does not work" means. Is it navigating but not replacing? Or not navigating at all? Are there any console errors or React warnings? Commented Jan 27, 2022 at 10:56
  • @DBS not navigating and no warnings and errors Commented Jan 27, 2022 at 11:01
  • Have you tried putting something like console.log(from) on the line above your navigate() to make sure everything's as-expected at that point? Commented Jan 27, 2022 at 11:03
  • I tried that and I got the pathname Commented Jan 27, 2022 at 11:06
  • @HareePrasad I think from URL is the same as the current URL, that's why it's not redirecting. Commented Jan 27, 2022 at 11:17

5 Answers 5

2

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

Sign up to request clarification or add additional context in comments.

Comments

1

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

navigate(from.replace('/', '') , { replace: true });

Comments

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...

Comments

0

Use this instead

return <Navigate to={from} replace />

Comments

-1

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>

2 Comments

thats because the correct usage is <Link to="/login">
Thank you about checking my mistake. @MichaelTaylor3D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.