如何从头开始为 React 实现自己的 useMemo

How to implement your own useMemo from Scratch, for React

基本上是这样的:

function MyComponent() {
  let [count, setCount] = useState(1)
  let memo = useMyMemo(() => new MyClass)

  return <div onClick={update}>{count}</div>

  function update() {
    setCount(count + 1)
  }
}

function useMyMemo(fn) {
  // what to do here?
}

class MyClass {

}

我希望 useMyMemo 每个组件实例 return 仅 class 1 个实例 。我如何设置它以在不使用任何现有的 React 钩子的情况下实现它?如果没有 React hooks 是不可能的,那他们为什么不呢?如果只能通过访问内部 API 实现,您会怎么做?

作为奖励,了解它如何传递 属性 依赖项,以及它如何使用它来确定备忘录是否应该无效会很有帮助。

我认为您是在描述 useMemo 的工作原理,假设您将 [] 作为 dependencies 参数传递。它应该已经为每个 MyComponent 实例创建了一个 MyClass 实例。但是,文档说 useMemo 的未来版本将不保证该值只被调用一次,因此您可能想尝试 useRef.

const memo = useRef(null);
if (!memo.current) {
  memo.current = new MyClass()
}

如果您希望它在依赖项更改时创建 MyClass 的新实例,您将不得不使用 useMemo(并接受该值偶尔可能无效的机会),或与以前的值进行自己的浅比较。像这样:

const useMyMemo = (create, dependencies) => {
  const val = React.useRef(create());
  const prevDependencies = React.useRef([]);
  if (!shallowEquals(dependencies, prevDependencies.current)) {
    val.current = create();
    prevDependencies.current = [...dependencies];
  }
  return val;
};

我会把 shallowEquals 的实现留给你,但我相信 lodash 有一个。

现在你真的要求一个不使用任何 React 钩子的函数,而我使用 useRef。如果您不想要 useRef,您可以创建自己的简单记忆函数,无论对 .current.

的更改如何始终 returns 相同的指针