(
fetchApi: FetchApi<ApiArgs>,
apiArgs: ApiArgs,
options: UseFetchOptions = {},
)
| 74 | * @returns [state, reload] |
| 75 | */ |
| 76 | const useFetch = <ApiArgs extends any[]>( |
| 77 | fetchApi: FetchApi<ApiArgs>, |
| 78 | apiArgs: ApiArgs, |
| 79 | options: UseFetchOptions = {}, |
| 80 | ): [State, () => void] => { |
| 81 | const { initData = null, onPreHandler, onSuccess, onFail, onFinally } = options; |
| 82 | const [state, dispatch] = useReducer(fetchReducer, { |
| 83 | isLoading: false, |
| 84 | isError: false, |
| 85 | error: '', |
| 86 | data: initData, |
| 87 | }); |
| 88 | |
| 89 | // 用于刷新请求 |
| 90 | const [refresh, setRefresh] = useState<boolean>(false); |
| 91 | const reload = () => setRefresh(!refresh); |
| 92 | |
| 93 | useDeepEffect(() => { |
| 94 | // 组件销毁时 abort 数据 |
| 95 | let didCancel = false; |
| 96 | const fetchData = async () => { |
| 97 | // 当请求中时,避免多次请求 |
| 98 | if (state.isLoading) return; |
| 99 | // 前置处理 |
| 100 | onPreHandler?.(); |
| 101 | // fetch init |
| 102 | dispatch({ type: 'FETCH_INIT' }); |
| 103 | try { |
| 104 | const res = await fetchApi(...apiArgs); |
| 105 | // 当组件销毁时,将isLoading,isError置为false |
| 106 | if (didCancel) { |
| 107 | dispatch({ type: 'FETCH_CANCEL' }); |
| 108 | return; |
| 109 | } |
| 110 | dispatch({ type: 'FETCH_SUCCESS', payload: res }); |
| 111 | onSuccess?.(res); |
| 112 | } catch (error) { |
| 113 | if (didCancel) { |
| 114 | dispatch({ type: 'FETCH_CANCEL' }); |
| 115 | return; |
| 116 | } |
| 117 | dispatch({ type: 'FETCH_FAILURE', payload: error }); |
| 118 | onFail?.(error); |
| 119 | } finally { |
| 120 | onFinally?.(); |
| 121 | } |
| 122 | }; |
| 123 | fetchData(); |
| 124 | return () => { |
| 125 | didCancel = true; |
| 126 | }; |
| 127 | }, [apiArgs, refresh]); |
| 128 | |
| 129 | return [state, reload]; |
| 130 | }; |
| 131 | |
| 132 | export default useFetch; |
no test coverage detected