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

流过昼夜 提交于 2021-01-28 18:45:26

问题


From what i understood from React documentation and other material across web, useCallback is used to avoid re-rendering of child component by ensuring that memoized version of callback is passed to it, thus referentially props remain same for child component. But all this is valid only if I am using React.memo on child component. Without React.memo, child component would re-render anyways. My question is what use is useCallback in this case i.e. without React.memo applied to child component. What are the other benefits of useCallback?


回答1:


React.memo ensures that a shallow comparison is performed when props enter a component and skips rendering of the component when they are equal.

Given a child component Cell: When applied to a function component that is created during the render of another, parent component, a new Cell component will be created on each render. This new Cell component will always make shallow comparisons on its props but it will be re-rendered on every render of its parent.

useCallback will however memoize this function callback Cell if it's dependency array does not change during a parent re-render. Alone a function component Cell wrapped in a useCallback will always re-render when it receives props, which will happen on every render of its parent. The difference however is that it's entire subtree is re-rendered if the component itself is recreated, as is the case when using React.memo by itself.

Paired together you can however get around re-rendering components defined inside of a parent.

As you will notice, when attempting to drag the Memoized cell, the one not wrapped in useCallback, no dragging happens. That is because the original element you attempt to drag is recreated as a new instance when it's parent re-renders. This concept is explained in more detail here

Example

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'));



回答2:


You might also need to pass a function to useEffect without changing useEffect on every render

For example:

import { useCallback, useEffect } from "react";

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

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

Real-world example with useDebounce:



来源:https://stackoverflow.com/questions/59663387/is-there-any-benefit-of-using-usecallback-without-react-memo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!