该系列其他文章可以点击查看专栏👉🏻👉🏻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 天,点击查看活动详情