52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
import { useState, useEffect, useRef, useReducer } from "react";
|
|
|
|
|
|
export type RequestContext<DataType> = {
|
|
data?: DataType;
|
|
error?: any;
|
|
loading: boolean;
|
|
refresh: () => void;
|
|
}
|
|
|
|
/**
|
|
* @param p
|
|
* @returns
|
|
* @todo deal refresh when loading
|
|
*/
|
|
const useRequest = <DataType = any>(p: () => Promise<DataType>, dependences?: any[]): RequestContext<DataType> => {
|
|
const [data, setData] = useState<DataType | undefined>()
|
|
const [error, setError] = useState<any>();
|
|
const [loading, setLoading] = useState(false);
|
|
const abort = useRef(false);
|
|
const [_, refresh] = useReducer(s => s + 1, 0);
|
|
|
|
useEffect(() => {
|
|
const doFetch = async () => {
|
|
setLoading(true);
|
|
abort.current = false;
|
|
try {
|
|
const data = await p();
|
|
if (!abort.current) {
|
|
setData(data);
|
|
}
|
|
} catch (e) {
|
|
if (!abort.current) {
|
|
setError(e);
|
|
}
|
|
} finally {
|
|
if (!abort.current) {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
};
|
|
doFetch();
|
|
return () => {
|
|
abort.current = true;
|
|
};
|
|
}, dependences ? [...dependences, _] : [_]);
|
|
|
|
return { data, error, loading, refresh };
|
|
};
|
|
|
|
export default useRequest;
|