0
votes

I have a separate fetch request function that logins user and saves auth token to localStorage, then my data request fetch should be send with that saved token bearer, but data fetch doesn't wait for token and receives Unauthorized access code.

My data request fetch looks like this :


// to check for fetch err

function findErr(response) {
    try {
        if (response.status >= 200 && response.status <= 299) {
            return response.json();
        } else if (response.status === 401) {
            throw Error(response.statusText);
        } else if (!response.ok) {
            throw Error(response.statusText);
        } else {
            if (response.ok) {
                return response.data;
            }
        }
    } catch (error) {
        console.log("caught error: ", error);
    }
}



const token = JSON.parse(localStorage.getItem("token"));

// actual fetch request

export async function getData() {
    const url = `${URL}/data`;

    var obj = {
        method: "GET",
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
            Authorization: "Bearer " + `${token}`,
        },
    };

    const data = await fetch(url, obj)
        .then((response) => findErr(response))
    
        .then((result) => {
            return result.data;
        });

    return data;
}


My fetch requests are in a different js file, I'm importing them in my components like this:

import React, { useState, useEffect } from "react";


function getInfo() {

const [info, setInfo] = useState()

const importGetDataFunc = async () => {
        const data = await getData();

        setInfo(data);
    };

useEffect(() => {
        importGetDataFunc();
    
    }, []);
    return (
        <div>
            
        </div>
    )
}

export default getInfo


Now when I go to the getInfo component after login at first fetch request returns 401, but after I refresh the page fetch request goes with token bearer and data gets returned. My problem is that I don't know how to make getData() fetch request to wait until it gets token from localStorage or retry fetch request on 401 code. I tried to implement if statement like this


useEffect(() => {

if(token){
        importGetDataFunc();
}
    }, []);

where useEffect would check if token is in localStorage and only then fire fetch request, but it didn't work. Any help on how I can handle this would be greatly appreciated.

2

2 Answers

2
votes

You are close. You need to add token as a dependency to your useEffect. Also, you need to move your token fetching logic into your component.

Something like this should work:

import React, { useState, useEffect } from "react";


function getInfo() {

const [info, setInfo] = useState()
const token = JSON.parse(localStorage.getItem("token"));

const importGetDataFunc = async () => {
        const data = await getData();

        setInfo(data);
    };

useEffect(() => {
        if(token) {
           importGetDataFunc(token);
        }
    
    }, [token]);

    return (
        <div>
            
        </div>
    )
}

export default getInfo

You can also modify your importGetDataFunc to receive the token as a parameter.

const importGetDataFunc = async (token) => {
        const data = await getData(token);

        setInfo(data);
    };
export async function getData(token) {
    const url = `${URL}/data`;

    var obj = {
        method: "GET",
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
            Authorization: "Bearer " + `${token}`,
        },
    };

    const data = await fetch(url, obj)
        .then((response) => findErr(response))
    
        .then((result) => {
            return result.data;
        });

    return data;
}
0
votes

What actually helped me is to make a function to check for a token inside get fetch request, like this:


export const findToken = () => {
    const token =localStorage.getItem("token") 

    return token;
};
export async function getData(token) {
    const url = `${URL}/data`;

    var obj = {
        method: "GET",
        headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
            Authorization: "Bearer " + `${findToken()}`,
        },
    };

    const data = await fetch(url, obj)
        .then((response) => findErr(response))
    
        .then((result) => {
            return result.data;
        });

    return data;
}