快速开始
快速开始
import {
useQuery,
useMutation,
useQueryClient,
QueryClient,
QueryClientProvider,
} from "react-query";
import { getTodos, postTodo } from "../my-api";
// Create a client
const queryClient = new QueryClient();
function App() {
return (
// Provide the client to your App
<QueryClientProvider client={queryClient}>
<Todos />
</QueryClientProvider>
);
}
function Todos() {
// Access the client
const queryClient = useQueryClient();
// Queries
const query = useQuery("todos", getTodos);
// Mutations
const mutation = useMutation(postTodo, {
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries("todos");
},
});
return (
<div>
<ul>
{query.data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
<button
onClick={() => {
mutation.mutate({
id: Date.now(),
title: "Do Laundry",
});
}}
>
Add Todo
</button>
</div>
);
}
render(<App />, document.getElementById("root"));
Queries
查询是对一个异步数据源的声明性依赖,它与一个唯一的键相联系。查询可以与任何基于 Promise 的方法(包括 GET 和 POST 方法)一起使用,从服务器上获取数据。如果你的方法修改了服务器上的数据,我们建议使用 Mutations 来代替。要在你的组件或自定义钩子中订阅一个查询,至少要用以下方式调用 useQuery 钩:
- 一个用于查询的唯一键
- 一个函数,返回一个 Promise,该 Promise 返回数据,或抛出一个错误
import { useQuery } from "react-query";
function App() {
const info = useQuery("todos", fetchTodoList);
}
你提供的唯一键在内部用于重新获取、缓存和在整个应用程序中共享你的查询。useQuery 返回的查询结果包含了所有关于查询的信息,你将需要这些信息来进行模板设计和对数据的其他使用。
const result = useQuery("todos", fetchTodoList);
result
对象包含一些非常重要的状态,你需要注意这些状态才能有成效。一个查询在任何时候都只能处于以下状态之一。
isLoading'或
status === ’loading’` - 查询没有数据,目前正在获取。isError
或status === 'error'
- 查询遇到了一个错误isSuccess
或status === 'success'
- 查询成功,数据可用。isIdle
或status === 'idle'
- 查询目前处于禁用状态(稍后你会了解更多关于这个的信息
除了这些主要的状态,根据查询的状态,还有更多的信息可用。
error
- 如果查询处于isError
状态,错误可以通过error
属性获得。data
- 如果查询处于成功'状态,数据可通过
data`属性获得。isFetching
- 在任何状态下,如果查询在任何时候都在获取(包括后台重新获取)isFetching
将是true
。
对于大多数查询来说,通常只需检查 isLoading 状态,然后是 isError 状态,最后是假设数据可用并呈现成功状态。
function Todos() {
const { isLoading, isError, data, error } = useQuery("todos", fetchTodoList);
if (isLoading) {
return <span>Loading...</span>;
}
if (isError) {
return <span>Error: {error.message}</span>;
}
// We can assume by this point that `isSuccess === true`
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
查询函数
查询函数实际上可以是任何返回 Promise 的函数。被返回的 Promise 应该是解决数据或抛出一个错误;下面所有的都是有效的查询函数配置。
useQuery(["todos"], fetchAllTodos);
useQuery(["todos", todoId], () => fetchTodoById(todoId));
useQuery(["todos", todoId], async () => {
const data = await fetchTodoById(todoId);
return data;
});
useQuery(["todos", todoId], ({ queryKey }) => fetchTodoById(queryKey[1]));
对于 React Query 来说,要确定一个查询有错误,查询函数必须抛出。在查询函数中抛出的任何错误都将被持久化在查询的错误状态上。
const { error } = useQuery(["todos", todoId], async () => {
if (somethingGoesWrong) {
throw new Error("Oh no!");
}
return data;
});
虽然大多数工具,如 axios 或 graphql-request,都会对不成功的 HTTP 调用自动抛出错误,但有些工具,如 fetch,默认是不抛出错误的。如果是这种情况,你就需要自己抛出这些错误。这里有一个简单的方法,用流行的 fetch API 做到这一点。
useQuery(["todos", todoId], async () => {
const response = await fetch("/todos/" + todoId);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
});
查询键不仅仅是为了唯一地识别你正在获取的数据,而且还方便地传递到你的查询函数中,虽然并不总是必要的,但这使得在需要时可以提取你的查询函数。
function Todos({ status, page }) {
const result = useQuery(["todos", { status, page }], fetchTodoList);
}
// Access the key, status and page variables in your query function!
function fetchTodoList({ queryKey }) {
const [_key, { status, page }] = queryKey;
return new Promise();
}