Есть ли польза от использования useCallback без React.memo? - PullRequest
0 голосов
/ 09 января 2020

Из того, что я понял из документации React и другого материала в Интернете, useCallback используется, чтобы избежать повторного рендеринга дочернего компонента, гарантируя, что запомненная версия обратного вызова передается ему, таким образом, ссылочные реквизиты остаются такими же для дочернего компонента. Но все это действительно только в том случае, если я использую React.memo для дочернего компонента. Без React.memo дочерний компонент будет перерисовываться в любом случае. Мой вопрос в том, что использовать useCallback в этом случае, т.е. без React.memo, примененного к дочернему компоненту. Каковы другие преимущества использования CallCallback?

1 Ответ

0 голосов
/ 08 марта 2020

React.memo обеспечивает выполнение поверхностного сравнения, когда реквизиты входят в компонент, и пропускает рендеринг компонента, когда они равны.

Заданный дочерний компонент Ячейка: При применении к созданному компоненту функции во время рендеринга другого, родительского компонента, новый компонент Cell будет создаваться при каждом рендеринге. Этот новый компонент Cell всегда будет выполнять поверхностные сравнения на своих объектах, но он будет перерисовываться при каждом рендеринге своего родителя.

useCallback, однако, запоминает этот обратный вызов функции Cell, если его массив зависимостей не изменяется во время родителя. повторная визуализация. В одиночку компонент функции Cell, обернутый в useCallback, всегда будет перерисовываться при получении реквизита, что происходит при каждом рендере его родителя. Разница, однако, заключается в том, что все его поддерево перерисовывается, если сам компонент воссоздается, как в случае использования самого 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'));
...