1

how can i redirect a user to a page he was previously in(let's say a detail page) or a page he's trying to access after successfully authenticating in react just like the request.GET.next in django with regular templates, i am using formik and django knox authentication for my server side. i know of the useLocation() hook, if so how can i store the previous or next url path in the uselocation state dynamically.

AUTH.JS

const {setIsLoggedIn,setUserData,isloggedIn,}=useContext(AuthContext)



const location=useLocation()

// console.log(location.state.from)
const loginformik=useFormik({
    initialValues:{
        // firstName:"",
        // lastName:"",
        email:"",
        password:"",   
    },
    validationSchema:Yup.object({
        email:Yup.string().email('invalid email address').required(),
        password:Yup.string().min(6,'password must be more than characters').required(),
    }),
    onSubmit:(values=>{
        fetch('http://127.0.0.1:8000/auth/login',{
            method:'POST',
            headers: {
                'Content-Type': 'application/json'
                // 'Content-Type': 'application/form-data',
              },
              body: JSON.stringify(values)

        }).then(res=>res.json()).then(data=>{
            
            console.log(data)
            localStorage.setItem('token',data.token)
            setUserData(data.user)
            setIsLoggedIn(true)
            if (data.status=== 202){
                setIsLoggedIn(true)
            }
        })
        
    })
})

DETAIL.js

const getPosts=async ()=> {
    const token=localStorage.getItem('token')
    console.log(token)
    const response= await fetch(`http://127.0.0.1:8000/${id}/`,{
        method:'GET',
        headers:{
            'Accept': 'application/json',
            'Authorization':`Token ${token}`,
            'Content-Type': 'application/json'
        }
    })
    console.log(response.url)
    if (response.status===401){
        navigate(`/auth?login`)
        localStorage.setItem('next_url',response.url)
    }
    const data=await response.json()

    setPost(data.music)

}
  • It seems you likely are using `react-router`, and if so, does this help answer your question? https://stackoverflow.com/questions/66289122/how-to-create-a-protected-route It's about protecting routes, i.e. redirecting to auth route, but covers the redirection back as well. – Drew Reese Jan 20 '23 at 09:22
  • any need protecting routes since i have permission,been setup in my server side(django)? – miracle godwin Jan 20 '23 at 09:59
  • I don't understand your question. Presumably you have something in the frontend that is redirecting to a route/page/component that has this log in function. Can you [edit] the post to include this part of the app, how a user lands on the login page, to see how you can redirect back to where they were? – Drew Reese Jan 20 '23 at 10:02
  • if a user is trying to access the upload page and he's not authenticated he is sent a http status response from django's end, then i wrote a conditional to redirect the user to login page based on the response from the server side – miracle godwin Jan 20 '23 at 20:12
  • Can you [edit] the post to include that code and component as part of your [mcve]? – Drew Reese Jan 20 '23 at 20:13
  • just added something hope thats' enough?... if it proves to be a problem we could have a google meet if that's okay by you. so you can see my whole screen – miracle godwin Jan 20 '23 at 20:21
  • Is this code all in the same component? Can you edit to include *complete* component examples, likely including the routes/pages/etc that each is rendered on? – Drew Reese Jan 20 '23 at 20:23
  • no they are in different components in same directory – miracle godwin Jan 20 '23 at 20:33

2 Answers2

1

In the Detail component use the useLocation hook to pass along the current location so that the Auth component knows where it can redirect back to.

Detail

import { ..., useLocation, useNavigate } from 'react-router';

...

const navigate = useNavigate();
const location = useLocation();

...


const getPosts = async () => {
  const token = localStorage.getItem('token');
  console.log(token);
  const response = await fetch(`http://127.0.0.1:8000/${id}/`, {
    method:'GET',
    headers:{
      'Accept': 'application/json',
      'Authorization':`Token ${token}`,
      'Content-Type': 'application/json'
    }
  });
  console.log(response.url);
  if (response.status === 401) {
    navigate(
      "/auth?login",
      {
        state: { from: location }, // <-- pass current location
        replace: true
      }
    );
    localStorage.setItem('next_url',response.url);
  }
  const data = await response.json();

  setPost(data.music);
}

Auth

import { ..., useLocation, useNavigate } from 'react-router';

...

const { setIsLoggedIn, setUserData, isloggedIn } = useContext(AuthContext);

const navigate = useNavigate();
const location = useLocation();

const loginformik = useFormik({
  initialValues: {
    // firstName:"",
    // lastName:"",
    email:"",
    password:"",   
  },
  validationSchema: Yup.object({
    email: Yup.string()
      .email('invalid email address')
      .required(),
    password: Yup.string()
      .min(6,'password must be more than characters')
      .required(),
  }),
  onSubmit: values => {
    fetch('http://127.0.0.1:8000/auth/login', {
      method:'POST',
      headers: {
        'Content-Type': 'application/json'
        // 'Content-Type': 'application/form-data',
      },
      body: JSON.stringify(values)
    })
      .then(res => res.json())
      .then(data => {
        console.log(data);
        localStorage.setItem('token', data.token);
        setUserData(data.user);
        setIsLoggedIn(true);
        if (data.status === 202) {
          setIsLoggedIn(true);
        }

         // Redirect back to previous location, or home
        const { state } = location;
        const { from } = state || { from: { pathname: "/" } };
        navigate(from, { replace: true });
      });
  },
});
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • alright buddy thanks on this. but how can i learn more on this uselocation? like you said PROTECTEDROUTES tried searching on them but mostly where resolved with redux – miracle godwin Jan 20 '23 at 20:55
  • @miraclegodwin Yes, that would be if you had a "API/service" module to control the network requests. You could/would check the response status codes and if a user was not authenticated dispatch an update to the Auth context. The protected routes would read the Auth context value and know if a current user was allowed access to the current route or not. – Drew Reese Jan 20 '23 at 20:58
  • { state: { from: location }, // <-- pass current location replace: true } like you stated here from : location the issue now is how do i get that from location dynamically(how will the system recognize such location)? – miracle godwin Jan 20 '23 at 20:58
  • @miraclegodwin It is the `location` object returned from the `useLocation` hook. The router knows what it is currently matching and rendering. – Drew Reese Jan 20 '23 at 20:59
  • actually currently my code is able to read if s user is to be given access to a page or not – miracle godwin Jan 20 '23 at 20:59
  • { state: { from: location }, // this funtionality need to be accesible in all components – miracle godwin Jan 21 '23 at 00:49
  • @miraclegodwin That specific line can be made available in any React component accessing `location` using the `useLocation` hook. It's only used to grab the current location for a redirect so the receiving component knows where the navigation action originated from. – Drew Reese Jan 21 '23 at 01:13
  • it just worked on the particular component.. thanks but pasting such line that stores the path on every component that need its... is not quite professional – miracle godwin Jan 21 '23 at 09:28
  • how about pasting it on the root component like app.js? – miracle godwin Jan 21 '23 at 09:28
  • it worked just had to move that line of code setting the location to its state to my nav component.... thanks alot – miracle godwin Jan 21 '23 at 10:47
  • @miraclegodwin Welcome, glad you have a working solution. Cheers and good luck. – Drew Reese Jan 21 '23 at 23:48
0

Use react router Dom 6. It has useNavigation hook which works well. And u can do navigation programmatically.