数据更改 & 重新验证
Quaere 提供了 mutation 和它的 useMutation 作为一个远程数据更改的 hook。远程数据更改只能手动触发,而不像 useQuery 那样会自动触发。
另外,这个 hook 不会与其他 useMutation hook 共享状态。
const anMutation = mutation({
  // 必选,用于请求数据的函数。
  fetcher: (variables: TVars, context: MutationFunctionContext) =>
    Promise<TData>,
  // 选项
  ...options,
});const { data, error, trigger, reset, isMutating } = useMutation({
  mutation: anMutation,
  // 将会覆盖 mutation 函数中的选项
  ...options,
});API
返回值
- data:从- fetcher返回给定 key 的数据
- error:- fetcher中抛出的错误(或 undefined)
- trigger(variables):一个用于触发远程数据更改的函数
- reset:一个用于重置状态的函数(- data,- error,- isMutating)
- isMutating:有一个正在进行中的远程数据变更
选项
- 
gcTime: number | Infinity- 未使用或非活动缓存数据在内存中保留的时间,以毫秒为单位。当缓存数据变为未使用或非活动状态时,将在指定的持续时间后进行垃圾回收。如果设置了不同的缓存时间,将使用最长的时间。
- 如果设置为 Infinity,将禁用垃圾回收。
 
- 
networkMode: 'online' | 'always' | 'offlineFirst'- 默认值为 'online'
- 参见 Network Mode 请求更多信息。
 
- 默认值为 
- 
onSuccess: (data: TData, variables: TVariables, mutationInfo: MutationInfo) => Promise<unknown> | unknown- 此函数将在请求成功时触发,并传递请求的结果。
- 如果返回一个 Promise,将在继续之前等待和解析该 Promise。
 
- 
onError: (err: TError, variables: TVariables, mutationInfo: MutationInfo) => Promise<unknown> | unknown- 如果请求遇到错误,将触发此函数,并传递错误。
- 如果返回一个 Promise,将在继续之前等待和解析该 Promise。
 
- 
onSettled: (data: TData, error: TError, variables: TVariables, mutationInfo: MutationInfo) => Promise<unknown> | unknown- 此函数将在请求成功请求数据或遇到错误时触发,并传递数据或错误。
- 如果返回一个 Promise,将在继续之前等待和解析该 Promise。
 
- 
retry: boolean | number | (failureCount: number, error: TError) => boolean- 默认值为 0
- 如果为 false,失败的请求将不会重试。
- 如果为 true,失败的请求将无限重试。
- 如果设置为一个数字,例如 3,则失败的请求将重试,直到失败次数达到该数字为止。
 
- 默认值为 
- 
retryDelay: number | (retryAttempt: number, error: TError) => number- 此函数接收一个 retryAttempt整数和实际错误,并返回下一次尝试之前的延迟时间(以毫秒为单位)。
- 像 attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)这样的函数应用指数回退。
- 像 attempt => attempt * 1000这样的函数应用线性回退。
 
- 此函数接收一个 
- 
throwOnError: undefined | boolean | (error: TError) => boolean- 默认值为全局查询配置的 throwOnError值,即undefined
- 如果希望在渲染阶段抛出请求错误并传播到最近的错误边界,则将其设置为 true
- 将其设置为 false以禁用将错误抛出到错误边界的行为。
- 如果设置为一个函数,它将接收错误并返回一个布尔值,表示是否在错误边界中显示错误(true)或将错误返回为状态(false)。
 
- 默认值为全局查询配置的 
- 
meta: Record<string, unknown>- 如果设置,则存储附加信息, 可以通过 fetcher的第二个参数MutationFunctionContext的meta属性读取。
 
- 如果设置,则存储附加信息, 可以通过 
基本用法
import { mutation, useMutation } from "quaere";
 
const updateUserMutation = mutation({
  fetcher: (user) => axios.post("/user", user),
});
 
function App() {
  const { trigger, isMutating } = useMutation({ mutation: updateUserMutation });
 
  return (
    <button
      disabled={isMutating}
      onClick={async () => {
        try {
          const result = await trigger({ name: "johndoe" });
        } catch (e) {
          // 错误处理
        }
      }}
    >
      Update User
    </button>
  );
}如果你想在渲染时使用数据更改的结果,你可以从 useMutation 的返回值中获得它。
const { trigger, data, error } = useMutation({ mutation: addTodoMutation });乐观更新
很多情况下,应用本地的数据更改是一个让人感觉快速的好方法——不需要等待远程数据源。
const updateUserMutation = mutation({
  fetcher: (user) => axios.post("/user", user),
});
 
const userQuery = query({
  fetcher: () => axios.get("/user"),
});
 
function Profile() {
  const queryClient = useQueryClient();
  const { trigger, isMutating } = useMutation({ mutation: updateUserMutation });
  const { data, refetch } = useQuery({ query: userQuery });
 
  return (
    <div>
      <h1>My name is {data.name}.</h1>
      <button
        disabled={isMutating}
        onClick={async () => {
          try {
            const previousData = data;
            const newName = data.name.toUpperCase();
            const user = { ...previousData, name: newName };
 
            // 立即更新本地数据
            queryClient.setQueryData({ query: userQuery }, user);
            // 发送一个请求以更新数据
            await trigger(user);
          } catch (error) {
            // 请求错误,执行回滚
            queryClient.setQueryData({ query: userQuery }, previousData);
          } finally {
            // 错误或成功后重新请求数据
            refetch();
          }
        }}
      >
        Uppercase my name!
      </button>
    </div>
  );
}