import { useCallback, useEffect, useState } from 'react'; import { useSnackbar } from 'notistack'; export interface RestRequestOptions { endpoint: string; fetchFunction?: typeof fetch; } const useRest = ({ endpoint, fetchFunction = fetch }: RestRequestOptions) => { const { enqueueSnackbar } = useSnackbar(); const [saving, setSaving] = useState(false); const [data, setData] = useState(); const [errorMessage, setErrorMessage] = useState(); const handleError = useCallback( (error: any) => { const errorMessage = error.message || 'Unknown error'; enqueueSnackbar('Problem fetching: ' + errorMessage, { variant: 'error' }); setErrorMessage(errorMessage); }, [enqueueSnackbar] ); const loadData = useCallback(async () => { setData(undefined); setErrorMessage(undefined); try { const response = await fetchFunction(endpoint); if (response.status !== 200) { throw Error('Invalid status code: ' + response.status); } setData(await response.json()); } catch (error) { handleError(error); } }, [handleError, fetchFunction, endpoint]); const save = useCallback( async (data: D) => { setSaving(true); setErrorMessage(undefined); try { const response = await fetchFunction(endpoint, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }); if (response.status !== 200) { throw Error('Invalid status code: ' + response.status); } enqueueSnackbar('Update successful.', { variant: 'success' }); setData(await response.json()); } catch (error) { handleError(error); } finally { setSaving(false); } }, [enqueueSnackbar, handleError, fetchFunction, endpoint] ); const saveData = () => data && save(data); useEffect(() => { loadData(); }, [loadData]); return { loadData, saveData, saving, setData, data, errorMessage } as const; }; export default useRest;