手写useImmer

41 阅读1分钟

immutable在前端是一个很重要的概念,因为前端的对象有快对象和慢对象的分别,所以在更新状态时尽量用一个新对象去替换旧对象,immer就是为了帮助你生成immutable对象的库。但是在react框架里我们就需要使用useImmer hook更方便一点,下面就是useImmer的手写:

import { Draft, freeze, produce } from "immer";
import { useCallback, useState } from "react";

export type DraftFunction<S> = (draft: Draft<S>) => void;
export type ImmerHook<S> = [S, (updater: S | DraftFunction<S>) => void];
export function useImmer<S = unknown>(intialValue: S | (() => S)): ImmerHook<S>;

export function useImmer<T>(intialValue: T) {
  const [val, updateValue] = useState(() =>
    freeze(typeof intialValue === "function" ? intialValue() : intialValue)
  );
  return [
    val,
    useCallback((updater: T | DraftFunction<T>) => {
      if (typeof updater === "function") {
        updateValue(produce(updater as DraftFunction<T>));
      } else {
        updateValue(freeze(updater));
      }
    }, []),
  ];
}


大家可以想一个问题:produce API是要传两个参数,这里为什么只需要1个?答案我放在评论区