目录
- 入门 react-query 已于 2022-06-04 更新
- 深刻查询键及查问函数 已于 2022-06-08 更新
版本阐明
本教程基于 react-query@4
版本编写,此版本目前 (2022-06-08) 为 alpha 版本。
在线演示基于 stackblitz
平台
查询键常见问题
查询键的值不能反复,须要放弃惟一
设想一下这样的场景,在 localStorage 中设置了上面的数据,目标是以 userID 为键,把以后的用户数据保留到缓存内
const userId = 1;
localStorage.setItem(userId, {username: 'fed-orange'})
接着再把某商品的内容以 ProductId 为键,把当商品的数据保留到缓存内
const productId = 1;
localStorage.setItem(productId, {name: 'orange'})
此时,会发现你保留到 localStorage 仅仅只保留了你前面缓存的值。
同理,在 react-query 中,如果这么做同样会遇到这样的问题 申请用户数据
const usersQuery = useQuery([userId],
fetchUsers
);
申请商品数据
const productsQuery = useQuery([productId],
fetchProducts
);
如果 userId
与productId
雷同时,前面申请的数据会笼罩后面申请的数据!解决这个问题的方法是:能够在数组的第一个元素中,放一个字符串来标识以后的数据类型(能够参照笔者之前提到的设计查询键的小倡议中的内容),就能够解决这个问题。
const usersQuery = useQuery(['users', userId],
fetchUsers
);
const productsQuery = useQuery(['products', productId],
fetchProducts
);
这样做不仅能更好的写查询键,在你调试数据的过程里,在 DevTools 中你能很不便的辨别进去不同的数据(不要本人给本人挖坑,在 DevTools 是以查询键为维度列出所有缓存的数据)!
查问函数
查问函数应用小妙招
置信在之前的介绍外面,可能把你的思维禁锢在查问函数只能应用 fetch(或者 axios 之类的库)来调用 http 接口。然而实际上,所有的 Promise 函数,都能够作为查问函数。举个例子,浏览器中异步的 API 接口——获取以后定位的 API,能够封装为一个查问函数。
const getLocation = async () =>
new Promise((resolve, reject) => {navigator.geolocation.getCurrentPosition(resolve, reject);
});
接着在 useQuery
中应用下面的查问函数
在 stackblitz 查看例子
例子 1👇🏻
import * as React from 'react';
import {useQuery} from 'react-query';
export default function App() {const getLocation = async () =>
new Promise((resolve, reject) => {navigator.geolocation.getCurrentPosition(resolve, reject);
});
const locationQuery = useQuery(['location'], getLocation);
return (
<div>
<h1> 获取地理位置 </h1>
{locationQuery.isLoading ? ('地理位置获取中') : locationQuery.isError ? (locationQuery?.error?.message) : (
<p>
你的地理位置是:{locationQuery.data.coords.latitude},
{locationQuery.data.coords.longitude}
</p>
)}
</div>
);
}
自定义 hook 封装 react-query 的查问申请
后面举的例子中,很多的申请都非常简单,并且仅仅在一个中央应用,因而咱们无需对代码进行封装。然而如果申请自身波及到非常复杂的解决,并且可能在多个组件重复使用的时候,咱们又回到了最后的原点,发现很多反复代码须要复制粘贴!然而一旦你有这个念头的时候,就是万恶的开始,一旦你这么做了,前期的保护老本将大大增加,批改一个中央,你不得不把相似的代码都更改一遍,费时费力!
上面咱们把之前的申请仓库 issue 的例子抽离成自定义 hook,这个是 Github 中针对该 api 的相干阐明文档,有趣味的同学能够自行查阅:issues api 文档,如果想扩大相干性能欢送在 stackblitz 里 fork 后自行尝试。
咱们再来看一下之前的查问函数
const fetchData = ({queryKey}) => {const [, owner, repo] = queryKey;
return fetch(`https://api.github.com/repos/${owner}/${repo}/issues`, {
headers: {Authorization: '',},
}).then(async (response) => {
// 如果申请返回 status 不为 200 则抛出后端谬误
if (response.status !== 200) {const { message} = await response.json();
throw new Error(message);
}
return response.json();});
};
接下来咱们定义一个名为 useGithubIssuesQuery
的钩子
import {useQuery} from 'react-query';
const useGithubIssuesQuery = ({owner, repo}) => {const fetchData = ({ queryKey}) => {const [, owner, repo] = queryKey;
return fetch(`https://api.github.com/repos/${owner}/${repo}/issues`, {
headers: {Authorization: '',},
}).then(async (response) => {
// 如果申请返回 status 不为 200 则抛出后端谬误
if (response.status !== 200) {const { message} = await response.json();
throw new Error(message);
}
return response.json();});
};
return useQuery(['issues', owner, repo], fetchData);
};
export default useGithubIssuesQuery;
此时在 react 组件获取数据时,要做的仅仅是应用 useGithubIssuesQuery
钩子,传入 owner 及 repo 参数即可,其它的所有都不须要关怀,如果在别的组件中须要申请仓库 issue 相干的接口,只有应用 useGithubIssuesQuery
钩子即可。并且在前期增加性能时,只须要找到对应的自定义钩子并做相干改变即可,大大提高了开发效率。
在多个组件中援用雷同 key 值的数据,react-query 不会进行屡次申请,能够放心使用!
总结
查询键
- 请保障查询键的唯一性。如果有反复的查询键,将会导致数据笼罩问题
- 查询键的设计能够遵循从通用到特定的规定,第一个元素能够是字符串来形容数据类型
- 查询键的元素能够是字符串、数字、嵌套数组、对象
- 在查询键变动时(包含对象内的变动,react-query 将会进行深度比拟),react-query 将会从新调用查问函数
查问函数
- 查问函数能够是任何 Promise 函数,包含但不局限于 fetch、axios、graphql 申请、异步浏览器 api 等
其它
倡议针对须要简单解决且在多处应用的申请,封装自定义钩子来进步开发效率。