Skip to content

[RFC] usePageCacheState #2416

Open
Open
@Damon0820

Description

@Damon0820

功能介绍

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>
);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions