react-query手把手教程12-更改数据(useMutation)

3,573 阅读3分钟

该系列其他文章可以点击查看专栏👉🏻👉🏻react-query手把手教程系列

场景

对于任何一个状态库来说都试图解决以下两个问题:

  • 如何将状态传递给组件
  • 如何更新状态

之前的章节中,主要介绍的内容都是如何将现有的状态传递给组件,只是一个纯读取的操作。从本章节开始将为大家介绍如何更新状态。react-query为开发者提供了useMutation钩子来提升此类场景的开发体验。

实践

useMutation

mutation是突变的意思,相信使用过graphql的同学一定非常熟悉,这个词往往意味着,你向后端发送需要进行数据的更新的相关内容。

同样的在react-query中,你可以使用useMutation钩子来请求后端进行数据更新的操作。

下面将使用github的开放接口,为大家介绍如何通过useMutation修改你的github用户名:

import {useQuery, useMutation} from 'react-query'

// ①
async function changeName(newName) {
  const response = await fetch('https://api.github.com/user', {
    method: 'PATCH',
    headers: {
      authorization: `token {这里替换成你自己的github token}`,
      'content-type': 'application/json'
    },
    body: JSON.stringify({
      name: newName
    })
  })
  
  const result = await response.json()


  if (!response.ok) {
    throw new Error(result.message)
  }


  return result;
}


const Username = () => {
  // ②
  const userQuery = useQuery(["user"], fetchUser);
  // ③
  const changeNameMutation = useMutation(changeName);


  if (userQuery.isLoading) return <p>加载数据中...</p>;


  return (
    <>
      // ④
      <button 
        onClick={() => {
          const newName = prompt("你希望修改成什么名字?");
          changeNameMutation.mutate(newName);
        }}>
          {changeNameMutation.isLoading ? "更改中...":""}
          {userQuery.data.name}
      </button>
      // ⑤
      {changeNameMutation.isError && <p>{changeNameMutation.error}</p>}
      
      // ⑥
      {changeNameMutation.isSuccess &&
        <p>github用户名修改成功!欢迎回来: {changeNameMutation.data.name}.</p>
      }
    </>
  )
}

①:实现了一个请求github修改用户名的接口,请注意接口中headers传入的authorization字段,需要你自己在github上申请token填入。

②:这里实现了一个获取用户信息的查询,在未修改用户名时,默认展示当前请求到的数据

③:这里调用了useMutation钩子,创建了一个changeNameMutation

④:用户点击按钮,更改用户名的请求发送后,如果是在加载状态时,isLoading属性就为true。你无需自己记录接口正在请求的状态,大大简化了开发。

⑤:一旦后端报错,此时读取isError字段,就知道更新用户名失败,此时可以直接展示后端具体的报错信息。

⑥:当更改用户名成功后,你可以通过读取isSuccess状态来获取请求是否成功,如果成功,那么就直接展示后端返回的新用户名,你同样不需要单独使用变量存储,可以非常方便地读取到新的数值。

useMutation钩子不会在组件加载时就直接请求,它需要你手动调用mutate方法并传入请求参数才会生效。并且将所有与之相关的数据(isLoading当前是否正在请求,isError当前是否请求失败,isSuccess当前是否请求成功,data后端返回的成功数据),都记录下来,方便后续调用。

重置信息

在请求结束后,上面的例子中,changeNameMutation内将会保存相关的请求信息缓存。如果你已经不需要这些数据,可以通过调用reset方法进行清除。

在使用useMutation时传入配置项,请求成功后触发onSuccess回调,在回调内调用reset方法来清除当前mutation的存储状态,代码如下:

const timerRef = useRef()
const changeNameMutation = useMutation(changeName, {
  onSuccess: () => {
    timerRef.current = setTimeout(() => {
      changeNameMutation.reset()
    }, 3000)
  },
  onMutate: () => {
    clearTimeout(timerRef.current)
  }
});

此时我们就使用useMutation初步的完成了后端数据更新的操作。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情