Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] usePageCacheState #2416

Open
Damon0820 opened this issue Dec 22, 2023 · 2 comments
Open

[RFC] usePageCacheState #2416

Damon0820 opened this issue Dec 22, 2023 · 2 comments
Labels
feature New feature or request pr welcomed

Comments

@Damon0820
Copy link

Damon0820 commented Dec 22, 2023

功能介绍

usePageCacheState 用于页面级别的缓存处理方案,通过缓存记录当前页面完整状态,一般会缓存较多数据。
支持的功能:

  1. 支持可存储多条数据。默认缓存一条数据,或者传入subKey,根据subKey作为主键缓存多条数据。
  2. 支持设置缓存最大数量
  3. 内置记录数据创建时间、更新时间。支持单条数据的过期时间设置,可指定根据据[创建时间 | 更新时间]计算是否过期,并自动清空过期数据。
  4. 支持读写时,带上缓存数据版本号。缓存数据结构破坏性不兼容变更时,升级版本号,舍弃旧版本缓存数据,可简单解决旧缓存数据不兼容问题。

使用场景

此 hook 常用于提升用户操作体验的场景。比如用户在【创建xx表单页】需要填写表单项较多,经常会主动/不小心退出当前页面,希望同个登录用户再次进入【创建xx表单页】可以恢复刚填写的内容。而其他登录用户进入【创建xx表单页】是重新填写,不读取其他用户的缓存。同时可设置缓存最大数量防止浏览器本地内存溢出问题。可设置缓存过期时间,不回填过于老旧的操作缓存等。

接口设计

/** 单条记录的存储的数据类型 */
type UnitStorageState<T> = {
  subKey: Exclude<Options<T>['subKey'], undefined>;
  createTime: number;
  createTimeFormat: string;
  updateTime: number;
  updateTimeFormat: string;
  /** 用户数据 */
  data?: T;
};

interface Options<T> {
  /** 缓存类型 */
  storageType?: StorageType;
  /** 二级key。用于区分同个页面,不同用户的缓存 */
  subKey?: string;
  /** 过期时间 单位秒 s */
  expire?: number;
  /** 用于计算过期时间取值属性 */
  expireTimeProp?: ExpireTimeProp;
  /** 最大数量 */
  maxCount?: number;
  /** 缓存版本号 */
  version?: number | string;
}

export type StorageType = 'localStorage' | 'sessionStorage';
export type ExpireTimeProp = 'createTime' | 'updateTime';

export type SetUnitDataState<S> = S | ((prevState?: S) => S);

/** 单条记录的存储的数据类型 */
type UnitStorageState<T> = {
  subKey: Exclude<Options<T>['tsubKey'], undefined>;
  createTime: number;
  createTimeFormat: string;
  updateTime: number;
  updateTimeFormat: string;
  /** 用户数据 */
  data?: T;
};

interface Options<T> {
  /** 缓存类型 */
  storageType?: StorageType;
  /** 二级key。用于区分同个页面,不同用户的缓存 */
  subKey?: string;
  /** 过期时间 单位秒 s */
  expire?: number;
  /** 用于计算过期时间取值属性 */
  expireTimeProp?: ExpireTimeProp;
  /** 最大数量 */
  maxCount?: number;
  /** 缓存版本号 */
  version?: number | string;
}

usePageCacheState<T>(key: string, options?: Options<T>):  [unitData: T | undefined, (unitData: SetUnitDataState<T>) => void, {
  delete: (subKey?: string | undefined) => void;
  storageState: UnitStorageState<T>[] | undefined;
  setStorageState: (value?: UnitStorageState<T>[] | IFuncUpdater<UnitStorageState<T>[] | undefined> | undefined) => void
}]

使用示例

const [name, setName] = useState<string>();
const [age, setAge] = useState<number>();
const [pageCache, setPageCache, { delete: deletePageCache, storageState }] = usePageCacheState<{ props: any; name?: string; age?: number }>(
  'CREATE_PAGE_CACHE_KEY',
  {
    subKey: userId,
    maxCount: 20,
    expire: 3 * 24 * 3600,
    version: 'f1308000',
  }
);

/** set to Storage when deps mutation */
useEffect(() => {
  setPageCache({
    props,
    name,
    age,
    // others data should be cached...
  });
}, [props, name, age]);

/** initial state from cache data */
useEffect(() => {
  if (pageCache) {
    const { name, age } = pageCache;
    setName(name);
    setAge(age);
    // others cache data sync to state
  }
}, []);

return (
  <form
    onSubmit={() => {
      // submit success
      deletePageCache();
    }}
  >
    <label>姓名:</label>
    <input value={name} onChange={e => setName(e.target.value)}></input>
    <label>年龄:</label>
    <input value={age} onChange={e => setAge(Number(e.target.value))}></input>
  </form>
);
@crazylxr
Copy link
Collaborator

似乎没有补这个 subKey 怎么消费的?

@crazylxr
Copy link
Collaborator

欢迎来个 PR

@crazylxr crazylxr added pr welcomed feature New feature or request labels Apr 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request pr welcomed
Projects
None yet
Development

No branches or pull requests

2 participants