封装一个关于数据请求的hook
原文:https://www.robinwieruch.de/react-hooks-fetch-data/
案例目录

对应的hook
/**
* 一个关于请求数据的hook,关键点:
* 1. 数据初始化
* 2. loading indicator
* 3. error handling
* 4. 用 useReducer 管理状态
* 5. 在组件被卸载后防止 state 改变
*/
import { useState, useEffect, useReducer } from "react";
import axios from "axios";
const useDataApi = (initialData, initalUrl) => {
const [url, setUrl] = useState(initalUrl);
const [state, dispatch] = useReducer(dataFetchReducer, {
isLoading: false,
isError: false,
data: initialData
});
useEffect(() => {
// 在页面被卸载时,阻止组件state改变
let didCancel = false;
const fetchData = async () => {
dispatch({ type: "FETCH_INIT" });
try {
const result = await axios(url);
if (!didCancel)
dispatch({ type: "FETCH_SUCCESS", payload: result.data });
} catch (error) {
if (!didCancel) dispatch({ type: "FETCH_FAILURE" });
}
};
fetchData();
return () => (didCancel = true);
}, [url]);
return [state, setUrl];
};
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();
}
};
export default useDataApi;
App.jsx中的实践
import React, { useState, Fragment } from "react";
import useDataApi from "./hooks/useHackerNewsApi";
import "./styles.css";
export default function App() {
const [{ data, isLoading, isError }, doFetch] = useDataApi(
{ hits: [] },
"https://hn.algolia.com/api/v1/search?query=redux"
);
const [query, setQuery] = useState("redux");
return (
<Fragment>
<form
onSubmit={(e) => {
e.preventDefault();
doFetch(`https://hn.algolia.com/api/v1/search?query=${query}`);
}}
>
<input
type="text"
value={query}
onChange={(event) => setQuery(event.target.value)}
/>
<button type="submit">Search</button>
</form>
{isError && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.hits.map((item) => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)}
</Fragment>
);
}

浙公网安备 33010602011771号