Home > database >  React custom hook returning array and utilize the same in App component
React custom hook returning array and utilize the same in App component

Time:04-08

I have my App component defined as below;

function App() {
    const [state1, setState1] = useState({});
    const [state2, setState2] = useState({});
    const [isApiCallDone, setIsApiCallDone] = useState(false);

    const fetchFn = useMyCustomFetch();

    useEffect(() => {
        (async function() {
            try {
                let [state11] = await fetchFn('api/api1', {}, 'GET');
                let [state22] = await fetchFn('api/api2', {}, 'GET');
                setState1(state11); // Is there a better way to set this ?
                setState2(state22);
                setIsApiCallDone(true);
            } catch (e) {
                console.error(e);
            }
        })();
    }, []);
    
    useEffect(() => {
        if (Object.keys(state1).length > 0 && Object.keys(state2).length > 0) {
            // Set some other state variables on App
        }
    }, [state1, state2])
    
    
    return (
        <>
            <MyContextProvider>
                    {isApiCallDone && (
                        <MyComponent />
                    )
                    }
            </MyContextProvider>        
        </>
    
}

Also my useMyCustomFetch hook looks like below

export default function useMyCustomFetch() {
    const fetchData = async (url, reqData, reqType) => {
        try {
            var statusObj = {
                statMsg: null
            };
            const response = await fetch(url, reqOptions);
            if (!response.ok) {
                throw response;
            }
            statusObj.status = "success";
            const json = await response.json();
            return [json, statusObj];
        } catch (error) {
            statusObj.status = "error";
            return [null, statusObj];
        }

    }
    return fetchData;
}

My questions are;

  1. For the lines

    let [state11] = await fetchFn('api/api1', {}, 'GET'); setState1(state11);

I first assign it to a new variable state11 and then assign the same by calling setState1. Is there a better way to set the state1 directly?

  1. Is the usage of async function inside the useEffect fine ?

CodePudding user response:

If you don't want to use async functions, you can use the Promise.prototype.then() method to combine your calls like this :

useEffect(() => {
    fetchFn('api/api1', {}, 'GET').then(state => {
        setState1(state[0]);
        return fetchFn('api/api2', {}, 'GET')
    }).then(state => {
        setState2(state[0]);    
        setIsApiCallDone(true);
    }).catch(console.log);
}, []);

An other way to set this with an async function but more factorised is this way :

useEffect(() => {
    (async function() {
        try {
            await fetchFn('api/api1', {}, 'GET')
                .then(tab => tab[0])
                .then(setState1);

            
            await fetchFn('api/api2', {}, 'GET');
                .then(tab => tab[0])
                .then(setState2);

            setIsApiCallDone(true);
        } catch (e) {
            console.error(e);
        }
    })();
}, []);

Finally, the usage of the async function in an useEffect is not a problem.

CodePudding user response:

For Question 1:

You can directly setState like below without using state11.

    useEffect(() => {
    (async function () {
      try {
        setState1(
          (await fetchFn("https://reqres.in/api/users/1", {}, "GET"))[0]
        ); // Is there a better way to set this ?
        setState2(
          (await fetchFn("https://reqres.in/api/users/2", {}, "GET"))[0]
        );
        setIsApiCallDone(true);
      } catch (e) {
        console.error(e);
      }
    })();
  }, []);

For Question 2:

I don't see any problem using async & IIFE in the useEffect. In fact I like the way its done. Looks good to me.

Please find screenshot of the state being set properly in the console (I have used a dummy api url):

enter image description here

  • Related