Главная / Статьи

90% разработчиков React оптимизируют процесс перерисовки неправильно

Большинство разработчиков React оптимизируют процесс перерисовки неправильно. Где на самом деле проявляется влияние на производительность React и какие решения помогают, а также чек-лист для их применения.

Издатель: REACTAPP.TOP13 мин чтения2912 слов

Источники: 90% of React Developers Optimize Re-Renders Incorrectly — Here’s What Actually Works

В следующих заметках описывается практический подход к теме «90% разработчиков React оптимизируют процесс перерисовки неправильно — вот что действительно работает». Акцент делается на контрактах, проверках и заменяемых фрагментах кода, а не на мотивирующих формулировках. Во время этапа обзора сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и последствия частичной неудачи. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам кода, определите критерии успеха и не допускайте безответственного частичного выполнения задач.

Настоящая проблема: мы не понимаем, когда React перерисовывает элементы

Наш подход работает наилучшим образом, когда его рассматривают как измеримую поверхность. Сначала зафиксируйте один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию, прежде чем расширять объем работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. Старайтесь сохранять низкие затраты на обработку данных и откладывайте дорогостоящие вычисления с использованием мемоизации только после их измерения. Преждевременное применение мемоизации может скрыть ошибки, связанные с устаревшими данными.

День, когда вы наконец открыли React Profiler

Подход «День, когда проект наконец заработает», наиболее эффективен, если рассматривать его как измеримую величину. Соберите один пример успешной работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сделайте процесс отрисовки дешёвым и откладывайте сложные вычисления с использованием мемоизации только после их измерения. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

Основная истина: повторные отрисовки — не враг, а врагами являются ненужные отрисовки

Этап перерисовки The Core Truth работает наилучшим образом, когда его рассматривают как измеримую сферу. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте низкую стоимость процесса перерисовки и откладывайте дорогостоящие операции на этап мемоизации только после проведения измерений. Преждевременная мемоизация может скрыть ошибки связанные с устаревшими данными. Этап перерисовки The Core Truth работает наилучшим образом, когда его рассматривают как измеримую сферу. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте молчаливого частичного завершения работы.

Раздел 1: Ментальная модель, которая наконец помогла понять React

Для этапа «Ментальная стадия» раздела 1 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение стоимости заранее предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам. При следующем шаге, представляющем собой код или вызов инструмента, следует отдавать предпочтение структурированным выводам с проверкой схемы перед произвольными текстовыми описаниями.

React = движок выполнения функций

На этапе движка выполнения функций React необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Состояние следует размещать рядом с компонентом, ответственным за его изменение. Хранение всего в глобальном хранилище затрудняет выявление ошибок, связанных с временем выполнения.

Component(props) → JSX

Раздел 2: Почему ваши компоненты перерисовываются чаще, чем вы думаете

В разделе 2 «Почему ваш этап» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Состояние должно храниться вместе с компонентом, ответственным за его изменение. Хранение всего в глобальном хранилище затрудняет выявление проблем с временем выполнения. В разделе 2 «Почему ваш этап» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного завершения работы.

1. Встроенные объекты и функции

При работе над этапом «Встроенные объекты и функции» сначала запишите условия использования: необходимые входные данные, сигнал о успешном выполнении и последствия частичной неудачи. Такой список поможет избежать ошибок при последующих изменениях кода. Рядом с результатами работы функций записывайте время выполнения, а также стоимость токенов или запросов. Отображение затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену вычисляемых значений во время отрисовки.

<MyComponent options={{ theme: "dark" }} />
{} !== {}
onClick={() => doSomething()}

2. Слишком высокий уровень хранения состояния

При работе над этапом «2 State Lifted Too» сначала запишите описание контракта: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Храните конфигурацию отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену вычисляемых значений во время отрисовки.

3. Вычисляемое состояние, хранящееся как состояние

При работе над этапом «Хранение 3 производных состояний» сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте как успешный сценарий работы, так и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену производных значений во время отрисовки. При работе над этапом «Хранение 3 производных состояний» сначала запишите условия взаимодействия: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия результатам обработки, определите критерии успеха и не допускайте безусловного частичного завершения работы.

const [filtered, setFiltered] = useState([]);

useEffect(() => {
  setFiltered(items.filter(...));
}, [items]);

Раздел 3: Правило, которое всё изменило для меня

Этап «Раздел 3: Правила» работает наилучшим образом, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на раннем этапе предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Старайтесь сохранять низкие затраты на обработку данных и откладывайте дорогостоящие вычисления с использованием мемоизации только после их измерения. Преждевременное применение мемоизации может скрыть ошибки, связанные с устаревшими данными.

Раздел 4: 4 уровня контроля перерисовки в React

Раздел 4. Метод 4 этапов наилучшим образом работает, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сделайте процесс отрисовки простым и откладывайте затратные вычисления с использованием мемоизации только после их измерения. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

Уровень 1: Структурная оптимизация (самое важное)

Этап структурной оптимизации уровня 1 работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте низкие затраты на обработку данных и откладывайте дорогостоящие вычисления с использованием мемоизации только после проведения измерений. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными. Этап структурной оптимизации уровня 1 работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не допускайте молчаливого частичного завершения работы.

Уровень 2: Мемоизация (при необходимости)

На этапе мемоизации уровня 2 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Рядом с функциональными результатами следует записывать время выполнения и стоимость обработки токенов или запросов. Отображение затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Состояние следует хранить вместе с компонентом, ответственным за его изменение; размещение всего в глобальном хранилище затрудняет выявление ошибок, связанных с временем выполнения.

Уровень 3: Стабильность ссылок

На этапе стабильности уровня 3 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Состояние следует хранить рядом с компонентом, ответственным за его изменение. Хранение всего в глобальном хранилище затрудняет выявление ошибок, связанных с временем выполнения.

const handler = () => doSomething();
const handler = useCallback(() => {
  doSomething();
}, []);
const config = useMemo(() => ({
  theme: "dark"
}), []);

Уровень 4: Архитектурная изоляция

На этапе архитектурной изоляции уровня 4 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Состояние должно храниться вместе с компонентом, ответственным за его изменение. Хранение всего в глобальном хранилище затрудняет выявление проблем с временем выполнения. На этапе архитектурной изоляции уровня 4 необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного завершения работы.

Раздел 5: React.memo — наиболее часто неправильно используемая оптимизация

При работе над этапом React memo в разделе 5 сначала запишите условия использования: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Записывайте время выполнения и стоимость токенов или запросов рядом с результатами работы функций. Отслеживание затрат на раннем этапе предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену вычисляемых значений во время отрисовки.

Когда React.memo ничего не делает

При работе над этапом «Когда React.memo работает», сначала опишите контракт: необходимые входные данные, сигнал о успехе и что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену вычисляемых значений во время отрисовки.

Когда React.memo демонстрирует свою эффективность

При работе над этапом «Когда React memo Shines» сначала запишите контракт: необходимые входные данные, сигнал о успехе и что происходит при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Документируйте одновременно успешный и восстановительный пути. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Рассматривайте эффекты как синхронизацию с внешним миром, а не как замену вычисляемых значений во время отрисовки. При работе над этапом «Когда React memo Shines» сначала запишите контракт: необходимые входные данные, сигнал о успехе и что происходит при частичной неудаче. Такой список помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия результатам обработки, определите критерии успеха и не допускайте безусловного частичного завершения.

Раздел 6: Ловушка useCallback

Раздел 6. Метод useCallback работает наилучшим образом, если рассматривать его как объект с измеримыми показателями. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма его применения. Записывайте время выполнения, а также стоимость использования токенов или запросов вместе с функциональными результатами. Отслеживание затрат на раннем этапе помогает избежать неожиданных расходов при переходе с демо-среды в общедоступные среды. Старайтесь сохранять низкую стоимость процесса отрисовки и откладывайте дорогостоящие вычисления на этап мемоизации только после их измерения; преждевременная мемоизация может скрыть ошибки, связанные с устаревшими параметрами.

const handleClick = useCallback(() => {
  setCount(c => c + 1);
}, []);

Раздел 7: Скрытые затраты контекста

Раздел 7 «Скрытая стадия» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один пример успешной работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сделайте процесс отрисовки дешёвым и откладывайте затратные вычисления с использованием мемоизации только после их измерения. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

Плохо:

Этап «Плохой сценарий» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один пример успешного выполнения, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно путь успешного выполнения и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте низкую стоимость процесса генерации результатов и откладывайте дорогостоящие операции на этап мемоизации только после проведения измерений; преждевременная мемоизация может скрыть ошибки связанные с устаревшими данными.

<AuthContext.Provider value={{ user, theme }}>

Лучше:

Этап «Лучше» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. Когда какой-то шаг терпит неудачу, причина сбоя должна указывать на конкретную ответственность, а не на запутанную цепочку операций. Сохраняйте низкие затраты на обработку данных и откладывайте дорогостоящие вычисления с использованием мемоизации только после их измерения. Преждевременное применение мемоизации может скрыть ошибки, связанные с устаревшими данными.

<UserContext />
<ThemeContext />

Раздел 8: Списки, ключи и иллюзия стабильности

Этап работы с списками Section 8 работает наилучшим образом, если рассматривать его как измеримую поверхность. Зафиксируйте один идеальный пример выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задач. Сохраняйте низкие затраты на процесс генерации результатов и откладывайте дорогостоящие операции на этап мемоизации только после проведения измерений. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

items.map((item, i) => <Row key={i} />)
items.map(item => <Row key={item.id} />)

Раздел 9: Чек-лист личной эффективности

Раздел 9, посвящённый этапу разработки на уровне отдельных элементов, работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один пример успешного результата, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Записывайте временные показатели, а также стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на ранних этапах предотвращает неожиданные счёты при переходе от демо-среды к общедоступным средам. Старайтесь сохранять низкие затраты на обработку данных и откладывайте дорогостоящие операции на этап мемоизации только после их измерения. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

Раздел 10: Кардинальное изменение подхода

Раздел 10 «Большая сцена» работает наилучшим образом, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Сделайте процесс отрисовки дешёвым и откладывайте затратные вычисления с использованием мемоизации только после их измерения. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными.

Заключительные мысли: настоящая тайна

Заключительные мысли. Этап Real работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Документируйте как успешный, так и восстановительный пути выполнения. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Сохраняйте низкую стоимость процесса генерации результатов и откладывайте дорогостоящие операции на этап мемоизации только после проведения измерений. Преждевременная мемоизация может скрыть ошибки, связанные с устаревшими данными. Заключительные мысли. Этап Real работает наилучшим образом, когда его рассматривают как измеримую среду. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте молчаливого частичного завершения работы.

Производительность React и оптимизация

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

React Hooks и управление состоянием

Шаблоны и архитектура React

Разработка приложений на React в реальных условиях

Экосистема и инструменты React

Путь обучения React (от начинающих до продвинутых)

Безопасность и масштабирование приложений на React

Интервью по React и карьера в этой области

Последние обновления React

Ещё один факт, который может вас удивить

Разработка приложений на React с использованием ИИ

Чек-лист для работы