我应该在何时使用此钩子时将每个道具用useCallback或useMemo包装起来?

var*_*ius 12 reactjs react-hooks

随着反应钩现已我应该在功能部件的情况下,包裹用的道具通过各项功能useCallback并与其他所有的道具价值useMemo

还应该在我的组件中具有依赖于任何props值的自定义函数,我应该使用useCallback包装它吗?

有哪些好的做法来决定使用此钩子从组件中包装哪些prop或const值?

如果这样可以提高性能,为什么不一直这样做呢?

让我们考虑在包装点击处理程序并添加自定义逻辑的自定义按钮

function ExampleCustomButton({ onClick }) {
  const handleClick = useCallback(
    (event) => {
      if (typeof onClick === 'function') {
        onClick(event);
      }

      // do custom stuff

    },
    [onClick]
  );

  return <Button onClick={handleClick} />;
}
Run Code Online (Sandbox Code Playgroud)

让我们考虑在包装点击处理程序并根据条件添加自定义逻辑的自定义按钮

function ExampleCustomButton({ someBool }) {
  const handleClick = useCallback(
    (event) => {
      if (someBool) {
        // do custom stuff
      }
    },
    [someBool]
  );

  return <Button onClick={handleClick} />;
}
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,我应该用useCallback包装我的处理程序吗?

与使用备忘录类似的情况。

function ExampleCustomButton({ someBool }) {
  const memoizedSomeBool = useMemo(() => someBool, [someBool])
  const handleClick = useCallback(
    (event) => {
      if (memoizedSomeBool) {
        // do custom stuff
      }
    },
    [memoizedSomeBool]
  );

  return <Button onClick={handleClick} />;
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,我甚至将备注值传递给useCallback

另一种情况是,如果在组件树中许多组件记忆相同的值?这对性能有何影响?

jal*_*ooc 12

不值得,有多种原因:

  1. 即使是官方文档,您也应该只在必要时这样做。
  2. 请记住,过早的优化是万恶之源 :)
  3. 这使DX(开发人员经验)变得更加糟糕:它很难阅读;更难写;难以重构。
  4. 在处理原语时(例如您的示例),记笔记要比不做花费更多的CPU能力。原始值没有引用的概念,因此在它们中没有要记住的内容。另一方面,备忘录本身(和其他任何钩子一样)确实需要一些微小的处理,没有什么是免费的。即使它很小,也比没有传递任何东西(与仅传递原始图元相比),因此您将用这种方法射击自己的脚。

放在一起-键入所有的钩子要比将它们放置在应用程序中的用户花费更多的时间。遵循良好的旧规则:先测量,然后进行优化

  • “只在必要时才这样做”并不能回答任何问题。什么时候“有必要”?将 prop 的值更改为重新创建的函数将重新渲染子组件。所以我想这取决于重新渲染受影响的子组件的成本与使用“useCallback()”的成本。 (6认同)

Pan*_*olo 6

我同意@jalooc提出的原则

为了提供有关OP中展示的用例的更多信息,这是我的建议:

昂贵的儿童呈现

function Component() {
  const callback = useCallback(() => { dostuff }, [deps])

  return <Child prop={callback} />
}
Run Code Online (Sandbox Code Playgroud)

如果Child是要渲染的非常昂贵的组件,则上述说明是有意义的。因此,它可能像这样导出:

function Child() { 
   ...this takes significant CPU... 
}

// Export as a pure component
export default React.memo(Child)
Run Code Online (Sandbox Code Playgroud)

昂贵的计算

function Component() {
  const callback = useCallback(() => { dostuff }, [deps])

  return <Child prop={callback} />
}
Run Code Online (Sandbox Code Playgroud)

结论

  1. 做有意义的事情或表现不好的事情
  2. 组件内部的函数声明在每次渲染时都会更改。如果这导致派生昂贵的计算,请记住它(useCallback)或将其移出范围。
  3. 如果组件本身的渲染成本很高React.memo,请#2在必要时借助进行纯化
  4. 如果重新计算本身很昂贵,请记住它(useMemo
  5. 做有意义的事情或表现不好的事情

  • 此外,当将渲染阶段创建的对象传递到用“React.memo”包装的组件时,“useMemo”是必需的 (2认同)