自定义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将缓存的值set到state上即可。
问题
上述方案并非没有问题,当fetchUserInfo方法在另一个组件内的hook方法后执行,数据并不会同步到先前使用hook的组件内。
关于这个问题,如果可以确保fetchUserInfo方法在另一个使用该hook的组件初始化前执行,则不会导致问题
如果需要fetchUserInfo方法执行后将数据同步到先前使用该hook的组件内,可以hook方法中收集每次hook调用的set方法,并在fetchUserInfo内触发set行为
推荐
实现数据缓存的功能,也可以使用ahooks库中提供的useRequest方法