【问题标题】:How to implement your own useMemo from Scratch, for React如何从零开始为 React 实现自己的 useMemo
【发布时间】:2019-12-17 20:47:30
【问题描述】:

基本上是这样的:

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每个组件实例只返回 1 个类实例。我如何设置它来实现它而不使用任何现有的 React 钩子?如果没有 React 钩子是不可能的,他们为什么不呢?如果只能通过访问内部 API 来实现,你会怎么做?

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

【问题讨论】:

  • 不是答案,但您需要深入研究 React 内部结构才能做到这一点。 Hooks 之所以起作用,是因为 React 知道它当前正在调用的组件函数。 useState 和这样的人使用内部信息来完成他们的工作(请参阅整个 ReactHooks.js file 中的 resolveDispatcher 调用),它们基本上是调用“调度程序”对象的包装器。一个这样的调度程序被实现here

标签: javascript reactjs memoization internals


【解决方案1】:

假设您将 [] 作为依赖项参数传递,我认为您正在描述 useMemo 的工作原理。它应该已经为每个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 发生什么变化,它总是返回相同的指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 2021-06-04
    • 2017-09-08
    相关资源
    最近更新 更多