Search code examples
reactjsreact-nativereact-router-dom

unable to redirect with this command navigate('/login?redirect=shipping') on react router dom i am using version 6


I am following a course in that course instructor wrote

react router dom version 5

const checkoutHandler = () => {
history.push('/login?redirect=shipping')
}

the above code is working fine in that course video,he is logging in and redirecting to shipping page

now i am using version 6 i changed above code to, i am unable to redirect to shipping

   import {useNavigate} from 'react-router-dom';

   const navigate=useNavigate();

   const checkoutHandler=()=>{
   navigate('/login?redirect=shipping')

}

and i can't understand what this '/login?navigate=shipping' command is doing exactly, why i am not able to rdirect.

MRE

        App.js
        <Routes>
        <Route path='/cart' element={<CartScreen/>}/>
        <Route path='/login' element={<LoginScreen/>}/>
        <Route path='/shipping' element={<ShippingScreen/>}/>
        <Route path='/' element={<HomeScreen/>} exact/>
        </Routes>

CartScreen , Click on Checkout.

 const checkoutHandler=()=>{
        navigate('/login?navigate=shipping')
}

Takes you to Login page Fill in Form Hit Login login screen

       const redirect = location.search ? 
        location.search.split('=')[1] : '/'

       useEffect(() => {
       if (localStorage.getItem('userInfo') !== null) {
       navigate(redirect)
       }
       }, [])

        isSuccess && navigate('/')

Solution

  • Issue

    The issue is that react-router-dom@6 is capable of both absolute and relative path routing. The difference is that absolute paths start with a leading "/" character while relative paths do not.

    The redirect target is "shipping" since the queryString is "?redirect=shipping"

    navigate('/login?redirect=shipping');
    

    In the LoginScreen component the code is accessing the location.searchand getting the"shipping"` value and attempting to navigate there.

    const redirect = location.search ? location.search.split('=')[1] : '/'
    
    useEffect(() => {
      if (localStorage.getItem('userInfo') !== null) {
        navigate(redirect); // <-- navigate("shipping")
      }
    }, []);
    

    The result of this is a relative navigation from the current route path "/login" to "/login/shipping" since the leading "/" is missing.

    Solution

    Use the useSearchParams hook to access the queryString (instead of the "hackish" string manipulation), and navigate correctly to the "/shipping" route.

    Example:

    import { useNavigate, useSearchParams } from 'react-router-dom';
    
    ...
    
    const navigate = useNavigate();
    const [searchParams] = useSearchParams();
    
    const redirect = searchParams.get("redirect");
    
    useEffect(() => {
      if (JSON.parse(localStorage.getItem('userInfo'))) {
        navigate(`/${redirect}`); // <-- navigate("/shipping")
      }
    }, [redirect]);