数据更新

在React Query中,数据更新功能主要对应HTTP POST、PUT、PATCH、DELETE等需要对数据和资源做出修改的请求。这些请求都有一个普遍的特点,就是在HTTP请求完成以后,应用页面上的数据会发生变化,需要重新加载。React Query中的useMutation Hook就提供了应用调用修改服务端数据请求的能力,只要再配合React Query中提供的缓存控制功能,就可以非常方便的完成修改服务端数据之后立刻对浏览器端的数据进行刷新的功能。

useMutation Hook的使用要比useQuery简单很多。useMutation主要是返回一个用于执行数据变化的对象,并通过这个对象中函数的调用来完成数据更改请求的一系列控制。

以下是useMutation的一个简单使用示例。

function NewThing() {
  const mutation = useMutation(newThingForm => {
    return axios.post(`/api/things`, newThingForm);
  });

  return (
    <>
      {mutation.isLoading ? <div>正在添加数据...</div> : null}
      {mutation.isError ? <div>出现错误:{mutation.error.message}</div> : null}
      <button onClick={() => mutation.mutate({ id: new ID(), name: 'the new one' })}>创建新记录</button>
    </>
  );
}

useQuery一样,useMutation也会返回statuserrordata等内容,并且其使用方式也于useQuery返回的内容相同。

useMutation返回的名为mutate的函数在使用的时候只需要注意其会把它所接受到的参数,直接传递给用于处理变更的变更函数。所以在定义变更处理时,需要留心变更函数中对于所接受的参数的处理。useMutation所返回的内容中常用的主要有以下这些。

  • mutate,返回一个签名为(variables: TVariables, { onSuccess, onSettled, onError }) => void的函数,主要用于启动数据更新过程。
  • mutateAsync,返回一个签名为(variables: TVariables, { onSuccess, onSettled, onError }) => Promise<TData>的异步函数,主要也用于启动数据更新过程。
  • reset,返回一个签名为() => void的函数,用于清除变更功能的内部状态,将其重置到其定义时的最原始状态。

useMutation在定义变更的时候,可以接受两个参数,第一个参数是用于处理变更的函数,其签名为(variables: TVariables) => Promise<TData>。从这个函数签名可以看出来,传递给mutate函数的参数是怎样被使用的。useMutation的另一个参数是一个对象,主要用于对useMutation定义的变更的特性进行配置,其中常用的配置字段主要有以下这些。

  • onMutate,接受一个签名为(variables: TVariables) => Promise<TContext | void> | TContext | void的函数,用于在变更被调用之前进行额外的处理使用。
  • onSuccess,接受一个签名为(data: TData, variables: TVariables, context?: TContext) => Promise<any> | void的处理函数,用于对成功执行变更事件的响应处理。
  • onError,接受一个签名为(error: TError, variables: TVariables, context?: TContext) => Promise<any> | void的处理函数,用于对执行变更失败以后的事件进行响应。
  • onSettled,接受一个签名为(data: TData, error: TError, variables: TVariables, context?: TContext) => Promise<any> | void的处理函数,用于执行变更以后所产生的事件的响应处理,相当于onSuccessonError的集合。

Warning

这里所介绍的useMutation Hook中并不包含对于查询缓存的控制,所以即便是成功执行了变更,也无法直接使界面上的数据发生自动刷新。如果需要完成数据自动刷新的功能,需要配合下一节的内容来使用。