// 使用useReducer 管理复杂的state
const dataFetchReducer = (state, action) => {
switch (action.type) {
case 'FETCH_INIT':
return {
...state,
isLoading: true,
isError: false
};
case 'FETCH_SUCCESS':
return {
...state,
isLoading: false,
isError: false,
data: action.payload,
};
case 'FETCH_FAILURE':
return {
...state,
isLoading: false,
isError: true,
};
default:
throw new Error();
}
};
// 自定义数据请求hook
const useDataApi = (initialUrl, initialData) => {
const [url, setUrl] = useState(initialUrl);
// useReducer的第二个参数为state的初始值
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
data: initialData,
});
useEffect(() => {
let didCancel = false;
const fetchData = async () => {
// 设置state为初始值
dispatch({ type: 'FETCH_INIT' });
try {
const result = await axios(url);
if (!didCancel) {
// 数据请求成功,变更state值
dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
}
} catch (error) {
if (!didCancel) {
// 数据请求失败,变更state值,state变更的值已在reducer中定义
dispatch({ type: 'FETCH_FAILURE' });
}
}
};
fetchData();
// 组件卸载时停止数据请求
return () => {
didCancel = true;
};
// 查询字符串变化时重新请求数据
}, [url]);
return [state, setUrl];
};
// 在组件中使用自定义hook,state绑定数据展示视图,查询触发setUrl
const [state, setUrl] = useDataApi(initialUrl, initialData)
参考自:https://www.robinwieruch.de/react-hooks-fetch-data/
网友评论