这篇文章介绍了我们如何使用React Query与TypeScript来获取数据。我们还将介绍React Query带来的一些好处。

什么是React Query?
React Query是一个神奇的库,它帮助我们管理网络服务请求中涉及的数据
它并没有进行实际的请求--我们仍然使用 fetch或者像axios这样的库来完成这个任务。
React Query会在组件生命周期的适当时候调用我们提出请求的代码。它还将来自请求的数据放入状态,并为获取过程提供其他有用的状态变量。
在此基础上,React Query提供了大量的功能,如缓存和重试,但我喜欢React Query的一点是,它可以清理我们的代码。
安装React Query
为了安装React Query,我们在终端运行以下命令:
npm install react-query
这个包已经包括了TypeScript类型。所以,不需要单独安装这些。
使用React Query
React Query需要在需要获取数据的组件上面有一个QueryClientProvider :
import { QueryClient, QueryClientProvider } from "react-query";
...
const queryClient = new QueryClient();
render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
rootElement
);
QueryClientProvider 从 包中取一个 类的实例。react-query QueryClient
在获取数据的组件中,一个来自react-query 包的useQuery 钩子允许我们指定获取数据的函数:
import { useQuery } from "react-query";
...
export function App() {
useQuery(
["character", { id: 1 }], // query key
getCharacter // fetching function
);
}
我们将一个键和我们的获取函数一起传入useQuery 。
在我们的例子中,键是一个元组,包含资源名称,"character" ,以及获取特定记录的参数,{ id: 1 } 。
取值函数是getCharacter - 我们稍后再看这个。
useQuery 有通用的参数,用于获取的数据类型和失败时的错误类型:
useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter
);
Error 是标准的错误对象。
Character 的类型如下:
type Character = {
name: string;
};
useQuery 返回有用的状态变量,可以去结构化:
const { status, error, data } = useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter
);
status包含我们在获取过程中的位置( 或 或 或 )。"idle""error""loading""success"error包含一个错误对象,如果获取错误的话。data包含已经成功获取的数据。
取值函数
获取函数的实现如下:
type Params = {
queryKey: [string, { id: number }];
};
async function getCharacter(params: Params) {
const [, { id }] = params.queryKey;
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
if (!response.ok) {
throw new Error("Problem fetching data");
}
const character = await response.json();
assertIsCharacter(character);
return character;
}
该函数接收查询键。在这个例子中,这是资源名称和参数,以获得一个特定的记录。
我们使用fetch 进行请求,如果响应不成功则抛出一个错误。React Query为我们管理这个错误,将status 状态设置为"error" ,将error 设置为Error 对象提出。
获取函数被期望从请求中返回我们想在组件中使用的数据。我们使用一个叫做assertIsCharacter 的类型断言函数来确保数据的类型正确:
function assertIsCharacter(character: any): asserts character is Character {
if (!("name" in character)) {
throw new Error("Not character");
}
}
完成组件
下面是组件实现的其余部分:
export function App() {
const { status, error, data } = useQuery<Character, Error>(
["character", { id: 1 }],
getCharacter
);
if (status === "loading") {
return <div>...</div>;
}
if (status === "error") {
return <div>{error!.message}</div>;
}
return data ? <h3>{data.name}</h3> : null;
}
我们使用status 状态,在获取过程中显示一个加载指示器。我们还使用status ,在出现错误时显示错误信息。
当数据被返回后,我们在一个h3 元素中显示其name 属性。
React查询的好处
请注意,我们不必使用useEffect ,也不必解决其async/await问题。我们不必把响应数据放在状态中,也不必处理组件在请求过程中被卸载的情况。React查询为我们处理了这些东西,让我们简化了代码。 😊
当应用程序重新获得焦点时,React query也会自动重新获取数据,这很好。当然,这可以被禁用,但我认为这是很好的默认行为。
React query的另一个特点是,如果出现错误,它会自动重试一个获取函数,最多3次。这也是很好的默认行为,特别是如果应用程序运行在一个连接不稳定的设备上。
这篇文章中的代码可以在CodeSandbox中找到,网址是codesandbox.io/s/react-que…