DevGang
Авторизоваться

React.memo() - ваш друг 

React.memo() - одна из тех вещей, которые должны быть частью арсенала каждого разработчика React. Она дает нам возможность запоминать компонент React. Как и в случае с любым другим инструментом, прежде чем мы углубимся в то, как использовать React.memo(), давайте сначала разберемся с проблемой.

Зачем нужна мемоизация?

Мемоизация - это общая концепция, которая в основном означает кеширование результатов каких-либо вычислений для последующего использования. Это метод оптимизации, который довольно широко используется в мире программирования.

Важно помнить, что всякий раз, когда используется мемоизация, должен быть критерий, который будет определять, когда кешированные результаты больше не действительны, и вычисление должно быть выполнено снова.

Чтобы понять проблему, которую это решает, рассмотрим следующий компонент React:

import { useState, Fragment } from "react";

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;

Простой компонент, который ведет счет, который можно увеличивать или уменьшать.

Теперь добавим еще один компонент в <App />. Чтобы упростить задачу, мы создадим компонент <Message />, который возвращает какое-либо сообщение в зависимости от идентификатора msgId, переданного ему в качестве реквизита.

function Message(props) {
  let msg = "hello, world";

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}

Мы сохранили здесь простоту, но представьте, что этот компонент <Message /> выполняет тяжелые вычисления или, возможно, отправляет запрос во внешний API, чтобы получить окончательное сообщение. Мы смоделируем эту ситуацию, добавив console.log() в микс всех фаворитов.

function Message(props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}

Давайте обновим компонент <App /> чтобы использовать <Message />.

import { useState, Fragment } from "react";

function Message(props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
}

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <Message msgId={1} />
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;

В видео ниже обратите особое внимание на тот факт, что при каждом изменении count выполняются тяжелые вычисления.

На этом этапе сделайте шаг назад и подумайте, насколько неэффективен наш пользовательский интерфейс в данный момент. count никак не влияет на <Message />, но все же каждый раз при обновлении count выполняется очень тяжелое вычисление. Мы хотим, чтобы вычисление происходило только при изменении msgId, потому что изменение msgId должно привести к другому сообщению.

React.memo () спешит на помощь

React.memo() компонент более высокого порядка. Он принимает компонент в качестве аргумента и запоминает результат. Мемоизированный результат обновляется только в случае изменения свойств исходного компонента.

Чтобы использовать React.memo(), просто передайте свой компонент в качестве аргумента и сохраните результат. Нашим компонентом <Message /> станет:

import { useState, Fragment, memo } from "react";

const Message = memo(function (props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
});

Примечание: я только импортировал сюда memo(). Если вы импортировали React, вы можете использовать вместо React.memo() просто memo().

Теперь наш код выглядит так:

import { useState, Fragment, memo } from "react";

const Message = memo(function (props) {
  let msg = "hello, world";

  console.log("Just performed some seriously heavy computation");

  if (props.msgId === 1) {
    msg = "hey there!";
  } else if (props.msgId === 2) {
    msg = "hola!";
  }

  return <p>{msg}</p>;
});

function App() {
  const [count, setCount] = useState(0);

  function handleDecrement() {
    setCount((oldCount) => --oldCount);
  }

  function handleIncrement() {
    setCount((oldCount) => ++oldCount);
  }

  return (
    <Fragment>
      <Message msgId={1} />
      <p>Count is {count}</p>
      <button onClick={handleDecrement}>-</button>
      <button onClick={handleIncrement}>+</button>
    </Fragment>
  );
}

export default App;

На этот раз обратите внимание, что вычисления выполняются, когда приложение обновляется, но изменение count больше не приводит к такому результату.

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

В подарок 100$ на счет при регистрации

Получить