目录
- 入门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等
其它
倡议针对须要简单解决且在多处应用的申请,封装自定义钩子来进步开发效率。