繁体   English   中英

在没有 React.memo 的情况下使用 useCallback 有什么好处吗?

[英]is there any benefit of using useCallback without React.memo?

从我从 React 文档和网络上的其他材料中了解到,useCallback 用于通过确保将回调的记忆版本传递给子组件来避免重新渲染子组件,因此子组件的引用 props 保持不变。 但这一切仅在我在子组件上使用 React.memo 时才有效。 没有 React.memo,子组件无论如何都会重新渲染。 我的问题是在这种情况下 useCallback 有什么用,即没有将 React.memo 应用于子组件。 useCallback 的其他好处是什么?

React.memo 确保在 props 进入组件时执行浅比较,并在它们相等时跳过组件的渲染。

给定一个子组件 Cell:当应用于在渲染另一个父组件期间创建的功能组件时,将在每次渲染时创建一个新的 Cell 组件。 这个新的 Cell 组件将始终对其 props 进行浅层比较,但它会在每次渲染其父级时重新渲染。

但是,如果它的依赖数组在父重新渲染期间没有更改,则 useCallback 将记住此函数回调 Cell。 单独一个包含在 useCallback 中的函数组件 Cell 在接收到 props 时将始终重新渲染,这将在其父级的每次渲染中发生。 然而不同的是,如果组件本身被重新创建,它的整个子树会被重新渲染,就像单独使用 React.memo 时的情况一样。

然而,配对在一起,您可以绕过重新渲染在父级内部定义的组件。

您会注意到,当尝试拖动 Memoized 单元格时,未包含在 useCallback 中的单元格不会发生拖动。 这是因为当它的父元素重新渲染时,您尝试拖动的原始元素被重新创建为新实例。 这个概念在这里有更详细的解释

例子

 const { useCallback, useState, useRef } = React; function App() { const [state, setState] = useState(false); const [title, setTitle] = useState(""); const Cell = useCallback(({ title }) => { console.log(`${title} rendering`); function onDragStart() { setState(true); } function onDragEnd() { setState(false); } return ( <div draggable onDragStart={onDragStart} onDragEnd={onDragEnd}> Drag {title} </div> ); }, []); const MemoizedCell = React.memo(({ title }) => { console.log(`${title} rendering`); function onDragStart() { setState(true); } function onDragEnd() { setState(false); } return ( <div draggable onDragStart={onDragStart} onDragEnd={onDragEnd}> Drag {title} </div> ); }); const MemoizedCallbackCell = useCallback( React.memo(({ title }) => { console.log(`${title} rendering`); function onDragStart() { setState(true); } function onDragEnd() { setState(false); } return ( <div draggable onDragStart={onDragStart} onDragEnd={onDragEnd}> Drag {title} <button onClick={() => setTitle(" Updated")}>Change Title</button> </div> ); }), [] ); return ( <div className="App"> <Cell title="Cell" /> <MemoizedCell title="Memoized Cell" /> <MemoizedCallbackCell title={"Memoized Callback Cell" + title} /> Is dragging {`${state}`} <br /> </div> ); } ReactDOM.render(<App />, document.getElementById('root'));

您可能还需要将函数传递给useEffect而不在每次渲染时更改useEffect

例如:

import { useCallback, useEffect } from "react";

function useExample() {
  function fn() {
    console.log("a function");
  }
  const callback = useCallback(fn, []);

  useEffect(() => {
    callback();
  }, [callback]);
}

useDebounce真实示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM