【React18】自定义hook中缓存数据

705 阅读2分钟

自定义hook中缓存数据

在页面中,有一些数据需要缓存下来并提供给多组件使用,比如用户信息。

实现方案

以获取用户信息为例:

import { useState, useEffect, useCallback } from "react";
import axios from "axios";

let fetchUserInfoCache;

export function useUserInfo() {
  const [userInfo, setUserInfo] = useState();
  
  // 调用接口并并获取用户信息的方法
  const fetchUserInfo = useCallback(async function () {
  
    // 假设项目中获取用户信息的接口路径为/api/userInfo
    // 使用fetchUserInfoCache去保存获取用户信息接口方法返回的Promise实例
    // 此后每次调用这个方法的时候都会使用缓存的Promise实例
    fetchUserInfoCache = fetchUserInfoCache || axios({ url: "/api/userInfo" });
    
    // 从Promise实例中获取接口返回数据并设置到userInfo状态
    const response = await fetchUserInfoCache;
    setUserInfo(response.data);

  }, []);

  useEffect(
    function () {
      // 判断如果有缓存的fetchUserInfoCache值
      // 则自动执行一次fetchUserInfo,主要是为了调用setUserInfo方法
      // 使userInfo状态有值
      if (fetchUserInfoCache) {
        fetchUserInfo();
      }
    },
    [fetchUserInfo]
  );
  return { userInfo, fetchUserInfo };

}

上面这段代码中,通过提供fetchUserInfo方法,使开发者可以手动调用此方法,比如在App.tsx中的一个合适时机调用fetchUserInfo方法

不过也可以直接在useEffect中去掉判断fetchUserInfoCache是否有值的逻辑,直接调用fetchUserInfo方法来获取值

具体如何做要看实际情况,如果获取用户信息即登录,则可以考虑直接调用fetchUserInfo的方式

关键点

在自定义hooks中缓存值的关键在于,在hook方法内部使用useEffect将缓存的值setstate上即可。

问题

上述方案并非没有问题,当fetchUserInfo方法在另一个组件内的hook方法后执行,数据并不会同步到先前使用hook的组件内。

关于这个问题,如果可以确保fetchUserInfo方法在另一个使用该hook的组件初始化前执行,则不会导致问题

如果需要fetchUserInfo方法执行后将数据同步到先前使用该hook的组件内,可以hook方法中收集每次hook调用的set方法,并在fetchUserInfo内触发set行为

推荐

实现数据缓存的功能,也可以使用ahooks库中提供的useRequest方法