0

I've been working on a way to make a general API request caller through a custom Axios hook.

const useAxiosFunction = () => {
    const [response, setResponse] = useState([]);
    const [error, setError] = useState('');
    const [loading, setLoading] = useState(false); 
    const [controller, setController] = useState();

    const fetchData = async (configObj) => {        

        try {
            setLoading(true);
            const ctrl = new AbortController();
            setController(ctrl);
            const res = await axios({...configObj, 
                signal: ctrl.signal                
            });            
            setResponse(res);
        } catch (err) {            
            setError(err.response.data);
        } finally {
            setLoading(false);
        }
    }

    useEffect(() => {        
        // useEffect cleanup function
        return () => controller && controller.abort();
    }, [controller]);
    
    return [response, error, loading, fetchData];
}

With the "configObjetc" parameter I can give all the info needed by Axios, like method and URL.

The problem lies in the delay produced by the re render needed at the time I call the fetchData function, since I want to use my "response" state immediately, for instance, after a button is pressed. So, how can I use the function of this hook the same way as if it was a promise calling the API directly, where I can use the response parameter just right away?

I have a functional component that returns JSX, where there is a button that triggers an onClick event called "handleClickTransfer" with a couple of parameters:

const [response, error, loading, fetchData] = useAxiosFunction();

const handleClickTransfer = (codOp, cvu, alias, email, comment) => {        
        fetchData({
            method: "GET",
            url: `${process.env.REACT_APP_ORQ_URL}/${process.env.REACT_APP_ORQ_VER}/consultaPagos/codigoOrdenPago/${codOp}`,   
            data: {"comment": refComment.current},        
            ...getHeadersToken()                        
        })

if(response.status === 200){
            modalProps.current = modalTransferencias(response.data.payments, codOp, cvu, alias, email, comment);
            handleShow();
        }else
            console.log(error);    

So when I click the button, the response state is not loaded yet, thus response.status is null, so the else condition is executed the first time. When I click the button again everything works fine since then. I need to get and use the response immediately after clicking on the button.

What have I tried? I tried moving the fetchData call within another async function and add an await when calling. I've also tried using useEffect hook, but it still goes through the else condition the first time, and I don't have access to all the parameters needed in the handleClick event. I find kinda tricky having to set new states for those too.

REA1990
  • 1
  • 1
  • Why not return `res` from the `fetchData` function? So that you can `const res = await fetchData()` in the event handler – Lin Du Jun 26 '23 at 03:01
  • I finally got this solved by returning a Promise in the AxiosHook function: fetchData. So every time I call an API request I just use .then and .catch to get the response and it works immediately wherever I call it in my component. I think your solution might work too, though. Thanks anyway. – REA1990 Jun 28 '23 at 13:40

0 Answers0