I'd like to use custom api request hook like so
// hooks.js
import { useState, useEffect } from 'react';
import api from '../utils/api';
function useAPI(fn, payload) {
const [state, setState] = useState({
loading: false,
data: null,
error: null,
});
const callAPI = async () => {
const setAPIState = update => setState({ ...state, ...update });
try {
setAPIState({ loading: true });
const data = await fn(payload);
setAPIState({ data, loading: false });
} catch (error) {
setAPIState({ error, loading: false });
}
};
useEffect(() => {
callAPI();
}, [fn, payload]);
return state;
}
export const useFetchTransactions = payload => {
const fetchTransactions = api.fetchTransactions;
return useAPI(fetchTransactions, payload);
};
and call it within my React component like so:
// Component.jsx
import { useState } from 'react';
import { useFetchTransactions } from '../hooks.js';
export default const Component = () => {
const [id, setID] = useState('');
const [date, setDate] = useState('12/13/21');
const { loading, data, error } = useFetchTransactions({ id, date });
return (
<div>{data.map...}</div>
)
}
However, this looks wrong. I think useFetchTransactions should live inside of a useEffect, so that the component then becomes something like:
// Updated Component.jsx
import { useState, useEffect } from 'react';
import { useFetchTransactions } from '../hooks.js';
export default const Component = () => {
const [id, setID] = useState('');
const [date, setDate] = useState('12/13/21');
const [apiState, setApiState] = useState({
data: null,
error: null,
loading: false
})
useEffect(() => {
const result = useFetchTransactions({ id, date });
setState({ ...apiState, ...result });
}, [date, id])
return (
<div>{apiState.data.map...}</div>
)
}
But the above feels cumbersome and redundant. Can anyone please lend some knowledge on this? Thanks!
you can do it like this
function useAPI(fn) { const [state, setState] = useState({ loading: false, data: null, error: null, }); const callAPI = async (payload) => { const setAPIState = update => setState({ ...state, ...update }); try { setAPIState({ loading: true }); const data = await fn(payload); setAPIState({ data, loading: false }); } catch (error) { setAPIState({ error, loading: false }); } }; return {state, callAPI}; } export const useFetchTransactions = () => { const fetchTransactions = api.fetchTransactions; return useAPI(fetchTransactions); };And then in your component
import { useState } from 'react'; import { useFetchTransactions } from '../hooks.js'; export default const Component = () => { const [id, setID] = useState(''); const [date, setDate] = useState('12/13/21'); const { callAPI, loading, data, error } = useFetchTransactions(); useEffect(() => { callAPI({ id, date }) }, [date, id]) return ( <div>{data.map(callAPI)}</div> ) }