关于前端:reactquery手把手教程②深入查询键及查询函数

31次阅读

共计 3385 个字符,预计需要花费 9 分钟才能阅读完成。

目录

  • 入门 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 等

其它

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

正文完
 0