Владислав Калачев

Учим useMemo на примерах — React Hooks

73

Доброго времени суток, друзья. Продолжим обзор хуков React и в данной статье поговорим о useMemo и React.memo. Современный React проводит множество оптимизаций «под капотом». Если вашему проекту требуется дополнительная оптимизация, то хук useMemo и React.memo вам в этом помогут. Давайте рассмотрим пример их использования в функциональных компонентах.

Видео на эту тему.

Как и зачем использовать useMemo?

Хук useMemo используется для мемоизации значений. Как это работает?  В функциональном компоненте у нас могут быть функции, которые производят промежуточные вычисления для получения новых знаний в компонентах. Явной иллюстрацией использования useMemo может быть именно такой «кейс».

Имеется компонент c двумя состояниями. Первое состояние по клику на текст будет менять его цвет, а второе это функция, которая по клику на кнопку, будет увеличивать счетчик на +1 и вызывать функцию sum(), в которой производится сложение входящего параметра с самим собой и как результат получится сумма этого вычисления. 

Пример:


const sum = n => {
	return n + n
 };

const MemoComponent = () => {
  const [num, setNum] = useState(1);
  const [isGreen, setIsGreen] = useState(true);
  const result = sum(num);

  return (
    <div>
      <h1 onClick={() => setIsGreen(!isGreen)}
        style={{ color: isGreen ? "green" : "red" }}
      >
        Example
      </h1>
      <h2>
        Sum {result}
      </h2>
      <button onClick={() => setNum(num + 1)}>➕</button>
    </div>
  );
};
export default Component;

В приведенном выше примере есть небольшая проблема. Каждый раз, когда мы кликаем по тексту,  происходит вызов setIsGreen, что приводит к перерендериванию компонента и, как следствие, повторный вызов функции sum(), хотя данный функционал не задействован и должен вызываться только по клику на кнопку +. Данное вычисление сейчас происходит при каждом рендере компонента, что с точки зрения оптимизации не эффективно. Для того, чтобы оптимизировать (мемоизавать) такие промежуточные вычисления требуется хук useMemo. Оборачиваем функцию sum() в useMemo и передаем вторым параметром в массиве num как зависимость, при изменении значения которой происходит повторный вызов функции sum().

Пример:


const sum = n => {
	return n + n
 };

const MemoComponent = () => {
  const [num, setNum] = useState(1);
  const [isGreen, setIsGreen] = useState(true);
  const result = useMemo(() => sum(num), [num]);
 
 return (
    <div>
      <h1 onClick={() => setIsGreen(!isGreen)}
        style={{ color: isGreen ? "green" : "red" }}
      >
        Example
      </h1>
      <h2>
        Sum {result}
      </h2>
      <button onClick={() => setNum(num + 1)}>➕</button>
    </div>
  );
};
export default MemoComponent;

Результат выполнения функции sum() был мемоизирован, теперь гораздо лучше. При изменении цвета текста не происходит повторный вызов функции sum(), а значит наша оптимизации прошла успешно.

React.memo

Для оптимизации рендеринга компонентов классов в React используется PureComponent и shouldComponentUpdate. Их альтернативой в функциональных компонентах является использование React.memo. Допустим у нас есть простой компонент, который рисует параграф текста.

Пример:


const Text = ({text}) => <p>{text}</p>
export default Text

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

Пример:


const Text = ({text}) => <div>{text}</div>
export default React.memo(Text)

Таким образом мы говорим React использовать результаты последнего рендеринга, без создания повторного рендеринга этого компонента.

Заключение

В данной статье мы рассмотрели на примерах, как и для чего использовать useMemo для мемоизации значений и использовали компонент высшего порядка React.memo как альтернативу PureComponent в компоненте класса. Надеюсь, что данная статья была вам полезна. Учитесь, думайте, пишите код. Удачного кодинга, друзья!

Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации. 

0

Комментарии:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *