Повышение эффективности рендеринга React‑компонентов

Мемоизация полезна для чистого дорогого вычисления, но Date.now меняется со временем: кэширование изменит наблюдаемое поведение. handleSend зависит от inputText и не может быть навсегда заморожен через [].

Короткий ответ

Что ответить на собеседовании

Мемоизация полезна для чистого дорогого вычисления, но Date.now меняется со временем: кэширование изменит наблюдаемое поведение. handleSend зависит от inputText и не может быть навсегда заморожен через [].

Подробный разбор

Ответ с пояснениями

Условие

В этом примере реализовано небольшое React‑приложение, где при каждом рендере вызывается дорогая функция и несколько дочерних компонентов перерисовываются без необходимости. Задача — предложить оптимизации, позволяющие избежать лишних вычислений и ререндеров, используя такие инструменты, как React.memo, useCallback, useMemo и другие подходы к управлению зависимостями.

import React from "react";
import { useState } from "react";

export const App = () => {
  const [baseNumber] = useState(9);
  const [inputText, setInputText] = useState("");

  const computeHeavy = () => {
    console.log("computeHeavy");
    return baseNumber + Date.now();
  };

  const handleSend = () => {
    console.log("send text = ", inputText);
  };

  return (
    <div>
      <TextField text={inputText} setText={setInputText} />
      <HeavySendButton onClick={handleSend} />

      <pre>{computeHeavy()}</pre>

      <button onClick={handleSend}>Кнопка отправки 2</button>
    </div>
  );
};

const HeavySendButton = ({ onClick }) => {
  console.log("SendButton render");
  return <button onClick={onClick}>Кнопка отправки 1</button>;
};

const TextField = ({ text, setText }) => {
  return (
    <input value={text} onChange={(event) => setText(event.target.value)} />
  );
};

Ответ

Мемоизация полезна для чистого дорогого вычисления, но Date.now меняется со временем: кэширование изменит наблюдаемое поведение. handleSend зависит от inputText и не может быть навсегда заморожен через [].

Сначала определите, что означает время в результате. Если это время создания компонента, сохраните его в state/ref; если текущие часы — обновляйте их отдельным механизмом. Для чистой функции от baseNumber используйте useMemo с зависимостью baseNumber.

HeavySendButton можно обернуть в React.memo, а handleSend — в useCallback с [inputText]. Это пропустит только рендеры, где текст не менялся: при вводе callback закономерно новый. TextField должен обновляться при изменении text. Оптимизацию начинайте с измерения реальной дороговизны; простой baseNumber + Date.now() сам по себе тяжёлой операцией не является.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее