目录

  • 入门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);

如果userIdproductId雷同时,前面申请的数据会笼罩后面申请的数据!解决这个问题的方法是:能够在数组的第一个元素中,放一个字符串来标识以后的数据类型(能够参照笔者之前提到的设计查询键的小倡议中的内容),就能够解决这个问题。

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等

其它

倡议针对须要简单解决且在多处应用的申请,封装自定义钩子来进步开发效率。