快速开始

快速开始

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’` - 查询没有数据,目前正在获取。
  • isErrorstatus === 'error'- 查询遇到了一个错误
  • isSuccessstatus === 'success' - 查询成功,数据可用。
  • isIdlestatus === '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();
}
上一页