'React custom utility function seeing Uncaught TypeError: Invalid attempt to destructure non-iterable instance

I have the following code in my React App component, where I am trying to get some JSON and want to send that to my custom hook.

const fetchFn = useCommonFetch();
const [user1, status1] = fetchFn('myapi/urls', {}, 'GET');

useEffect(() => {
    someCustomHookCall(user1); // Pass "user1" JSON info to someCustomHookCall
}, [user1])

Below is how the useCommonFetch looks;

import {useEffect, useState} from 'react';

export default function useCommonFetch() {
    const fetchData = async (url, reqData, requestType) => {
        try {
            var statusObj = {
                statMsg: null,
                errMsg: null,
                status: null,
            };
            var reqOptions = {
                credentials: 'same-origin'
            }
            if (requestType === 'POST') {
                reqOptions.headers = {};
                reqOptions.headers['Accept'] = 'application/json';
                reqOptions.method = 'POST';
                reqOptions.body = JSON.stringify(reqData);
            }
            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";
            if (error && error.status) {
                switch (error.status) {
                    case 401:
                        statusObj.errMsg = "Unauthorized";
                        console.error("Unauthorized: " + error.status);
                        break;
                    default:
                        statusObj.errMsg = "Sys error";
                }
            }
            return [null, statusObj];
        }

    }
    return fetchData;
}

I am getting the following error while running

Uncaught TypeError: Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a Symbol.iterator method.

Not sure what is wrong in the calling code.



Solution 1:[1]

The error occurs because you're trying to destructure a pending promise.
I have created a short codesandbox that suggests another way of achieving your expectation, but something causes the component to re-render nonstop.

Solution 2:[2]

fetchFn is an asynchronous function and it returns a promise(and not an array), I suggest you change the useCommonFetch as follows:

import {useEffect, useState} from 'react';

const fetchData = async (url, reqData, requestType) => {
  ...
}

export default function useCommonFetch(url, reqData, requestType) {
    const [state, setState] = useState([null, null]);
    
    useEffect(() => {
      async function getData() {
        const result = await fetchData(url, reqData, requestType);
        setState(result);
      }
      getData();
    }, [url, reqData, requestType])

    return state;
}

You can use it like this:

const [user1, status1] = useCommonFetch('myapi/urls', null, 'GET');

useEffect(() => {
  if(user1) {
    someCustomHookCall(user1); // Pass "user1" JSON info to someCustomHookCall
  }
}, [user1])

Edit vibrant-joliot-5yvg9r

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Art
Solution 2