/* eslint-disable react-hooks/exhaustive-deps */ import { Dispatch, SetStateAction, useEffect, useState } from "react"; export interface IData<T> { data: T; loading: boolean; setData: Dispatch<SetStateAction<T>>; updateData: () => any; } export function useData<T>(fetchFn: () => PromiseLike<T>, deps: any[] = []): IData<T> { const [trigger, setTrigger] = useState<boolean>(false); const [data, setData] = useState<T>(); const [loading, setLoading] = useState(true); useEffect(() => { async function fetch() { setLoading(true); try { const newData = await fetchFn(); setData(newData); } finally { setLoading(false); } } fetch(); }, [trigger, ...deps]); // do not include fetchFn here to allow inline functions as arg: useData(() => getAsync(), []) return { data, loading, setData, updateData: () => setTrigger(!trigger) } as IData<T>; }
Example component:
export function UserInfo(props: { userId: string }): React.ReactElement { const ds = useData(() => appDomain.IUserService.loadUser(props.userId), [props.userId]); const user = ds.data; return <div> Loading: {ds.loading} User name: {user?.name} <button type="button" onClick={ds.updateData}>Refresh</button> </div>; }
782700cookie-checkReact Hook: useData()