JeromeD3 / react-hooks

my hooks
0 stars 0 forks source link

useRequest缓存 --- 参数缓存 #3

Open JeromeD3 opened 1 year ago

JeromeD3 commented 1 year ago

缓存的数据包括 data 和 params,通过 params 缓存机制,我们可以记忆上一次请求的条件,并在下次初始化。

JeromeD3 commented 1 year ago

我们可以看到ahooks的案例,input框为需要缓存的参数

image

然后我们查看源代码,input绑定的state是来自于useRequest返回的params参数,说明useRequest对上一次传递的参数进行了缓存,那这个情况该如何实现呢?

image
JeromeD3 commented 1 year ago

useCachePlugin

新增代码如下:

import * as cache from '../utils/cache';
+import useCreation from '../../../useCreation';
const useCachePlugin = (fetchInstance, {
  cacheKey,
  staleTime = 0,
}) => {
  const _setCache = (key, cachedData) => {
    cache.setCache(key, cachedData);
  };

  const _getCache = (key) => {
    return cache.getCache(key);
  };
+ useCreation(() => {
+   if (!cacheKey) {
+     return;
+   }
+   const cacheData = _getCache(cacheKey);
+   if (cacheData && Object.hasOwnProperty.call(cacheData, 'data')) {
+     fetchInstance.state.data = cacheData.data;
+     fetchInstance.state.params = cacheData.params;
+     if (staleTime === -1 || new Date().getTime() - cacheData.time <= staleTime) {
+       fetchInstance.state.loading = false;
+     }
+   }
+ })
  if (!cacheKey) {
    return {};
  }

  return {
    onBefore: params => {
      const cacheData = _getCache(cacheKey, params);
      if (!cacheData || !Object.hasOwnProperty.call(cacheData, 'data')) {
        return {};
      }
      if (staleTime === -1 || new Date().getTime() - cacheData.time <= staleTime) {
        return {
          loading: false,
          data: cacheData?.data,
          returnNow: true
        };
      } else {
        return {
          data: cacheData?.data
        };
      }
    },
    onSuccess: (data, params) => {
      if (cacheKey) {
        _setCache(cacheKey, {
          data,
          params,
          time: new Date().getTime()
        });
      }
    }
  };
};

export default useCachePlugin;

我们从代码也可以清楚的看到,新增了useCreation这个hook。

实现原理

  1. (注意,如果不刷新的情况下,这个插件函数只会执行一次)
  2. 在这个插件一执行的时候,判断有无缓存
  3. 如果有缓存,我们就将缓存结果和缓存参数赋值给当前实例
  4. 这样内部状态改变,UI重新刷新,keyword本来会被初始化为初始值,但是我们有缓存
  5. 同时这要判断是否在staleTime中,也就是需不需要在规定时间内重新请求,是则loading = false,这样就给用户一种没有刷新的感觉
image
JeromeD3 commented 1 year ago
image

测试结果

  1. 我们可以看到,虽然输入框没有被清空,但是我们输出keyword的时候可以看到我们的想法是正确的。
  2. 当UI重新刷新的时候,state会重新初始化为上一次保存的结果(如果你没有执行setState,那就是最初的值)