Fezzo
Fezzo

Reputation: 3

React update state from the axios response

I have been trying to build this authentication verify component and I've been stuck.

What I'm trying to do is to make an axios get request to my backend server to verify if the user is logged in. The backend part works just fine. Keep in mind that the cookies are sent when they exist. What happens is that I send the user's cookies & headers with the request, to the backend, and then the server validates it, and then sends back a success response. I'm trying to change the react useState's state based on the axios response.

Here's my current code:

import { useEffect, useState } from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import apiurl from '../axios'; // custom axios interceptor

const AuthVerifyFunction = () => {
    const [isAuth, setIsAuth] = useState();

    const config = {
        headers: {
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest"
        }
    }

    const verifyAuth = () => {
        apiurl.get('/api/auth/verify', config)
            .then(res => {
                setIsAuth(res.data.success)
                console.log(res)
                console.log("isAuth:", isAuth);
            })
            .catch(err => {
                console.log(err)
            });
    }

    useEffect(() => {
        verifyAuth();
    }, []);

    return (
        <h1>{isAuth ? <Outlet /> : <Navigate to="/login" />}</h1>
    )

}

export default AuthVerifyFunction;

This is the success response i get back:

{data: {…}, status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
  config: {transitional: {…}, transformRequest: Array(1), transformResponse: Array(1), timeout: 0, adapter: ƒ, …}
  data: {success: true, authHeader: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZC…Tg4fQ.lX8piOnRb9-MQCS8mibMSmFfjBcCeTaC7sw-DgdwBl8'}
  headers: {content-length: '230', content-type: 'application/json; charset=utf-8'}
  request: XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: true, upload: XMLHttpRequestUpload, …}
  status: 200
  statusText: "OK"
  [[Prototype]]: Object

The part I've been stuck on is that I don't know how to not redirect the user before the async response, or in easy words, I just want to show the outlet if the response.data.success is true, if it isn't, then redirect them to /login.

If there's any other better way to do this, please let me know. Thank you in advance.

Upvotes: 0

Views: 757

Answers (2)

lpizzinidev
lpizzinidev

Reputation: 13289

You could use a isLoading state: set it to false when you receive a response from the API:

import { useEffect, useState } from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import apiurl from '../axios'; // custom axios interceptor

const AuthVerifyFunction = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [isAuth, setIsAuth] = useState();

  const config = {
    headers: {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
    },
  };

  const verifyAuth = () => {
    apiurl
      .get('/api/auth/verify', config)
      .then((res) => {
        setIsAuth(res.data.success);
        setIsLoading(false);
        console.log(res);
        console.log('isAuth:', isAuth);
      })
      .catch((err) => {
        console.log(err);
      });
  };

  useEffect(() => {
    verifyAuth();
  }, []);

  return (
    <h1>
      {isLoading ? (
        'Authenticating...'
      ) : isAuth ? (
        <Outlet />
      ) : (
        <Navigate to='/login' />
      )}
    </h1>
  );
};

export default AuthVerifyFunction;

Upvotes: 1

Eren Yusuf Duran
Eren Yusuf Duran

Reputation: 66

Maybe you should declare your initial state,so it won't be null

 const [isAuth, setIsAuth] = useState(false);

Upvotes: 0

Related Questions