Call React Custom Hook from a function

Viewed 41

I am writing a hook to get data from server (calling an API). This hook should be called when a component is loaded and also when a button is clicked where the button exists in the same component. (Actually I am using this in ReactNative where I want the hook to be called on refresh, but to make it simple I am taking button here)

Here is my hook:

export default function useApi() {
    const [data, setData] = useState({ loading: false, error: null, data: undefined });

    useEffect(() => {
        callApi();
    }, []);

    const callApi = async () => {
        let response;
        try {
            setData({ ...data, loading: true });
            response = await axios.get("url");
        } catch (e) {
            setData({ ...data, loading: false, error: e });
        } finally {
            setData({
                    ...data,
                    loading: false,
                    data: response.data,
                });
        }
    };
    return data;
};

My Component:

export default function SpecialComponent() {

const { loading, error, data } = useApi();

const getData = () => {
 //I need to get data using the hook here.
};

return (
   <div>
       { !loading && 
          <div>
              <div>{JSON.stringify(data)}</div> 
              <Button onClick={getData}>Got latest data</Button>
          </div>
       }

       { loading && <div>Loading...</div> }
   </div>
);

}

I thought about useEffect but again same problem. I am not sure if it is a right pattern to call a hook from useEffect.

Any help is highly appreciated.

1 Answers

Return the callApi function from the hook too.

export default function useApi() {
    const [data, setData] = useState({ loading: false, error: null, data: undefined });    
    const callApi = async () => {
        let response;
        try {
            setData({ ...data, loading: true });
            setData({
                ...data,
                loading: false,
                data: await axios.get("url").data
            });
        } catch (e) {
            setData({ ...data, loading: false, error: e });
        }
    };
    useEffect(callApi, []);
    return { data, callApi };
};
export default function SpecialComponent() {
    const { callApi, data } = useApi();
    const { loading, error, data } = data;
    return (
        <div>
            { loading
                ? <div>Loading...</div>
                : <div>
                    <div>{JSON.stringify(data)}</div>
                    <Button onClick={callApi}>Got latest data</Button>
                </div>
            }
        </div>
    );
}
Related