PurpleSchool — курсы программирования онлайн
  • Пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • AI для кодаНовое
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • AI для кодаНовое
    • Сообщество
    • PurpleПлюс
    • AI Собеседование
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Оптимизация производительности React: memo, lazy, Suspense, Profiler

    Оптимизация производительности React: memo, lazy, Suspense, Profiler

    Аватар автора Оптимизация производительности React: memo, lazy, Suspense, Profiler

    Антон Ларичев

    Иконка календаря15 июня 2026
    ReactPerformanceOptimizationFrontendmiddleИконка уровня middle
    Картинка поста Оптимизация производительности React: memo, lazy, Suspense, Profiler

    Введение

    Производительность React-приложения напрямую влияет на пользовательский опыт и бизнес-метрики. Медленные рендеры, лишние перерисовки и тяжёлые бандлы делают интерфейс неотзывчивым. К счастью, React предоставляет встроенные инструменты для борьбы с этими проблемами: React.memo, React.lazy, Suspense и Profiler. В этой статье разберём, как и когда применять каждый из них, чтобы получить ощутимый прирост скорости без преждевременной оптимизации.

    Понимание этих API критично для middle-разработчика: они закрывают три ключевых вопроса — что рендерить, когда рендерить и сколько это занимает.

    React.memo: мемоизация компонентов

    React.memo — это HOC, который запоминает результат рендера компонента и пропускает повторный вызов, если пропсы не изменились. По умолчанию сравнение поверхностное (Object.is для каждого пропа).

    import { memo } from 'react';
    
    // Компонент отрендерится только при изменении пропсов
    const ProductCard = memo(function ProductCard({ title, price }) {
      console.log('Рендер ProductCard:', title);
      return (
        <div className="card">
          <h3>{title}</h3>
          <span>{price} ₽</span>
        </div>
      );
    });
    

    Если пропсы — объекты или функции, поверхностного сравнения недостаточно. Здесь помогают useMemo и useCallback в родителе:

    function ProductList({ items }) {
      // Стабильная ссылка на обработчик — иначе memo бесполезен
      const handleClick = useCallback((id) => {
        console.log('Клик:', id);
      }, []);
    
      return items.map((item) => (
        <ProductCard
          key={item.id}
          title={item.title}
          price={item.price}
          onClick={handleClick}
        />
      ));
    }
    

    Для сложных пропсов можно передать кастомный компаратор вторым аргументом:

    const Chart = memo(
      function Chart({ data, config }) {
        return <canvas />;
      },
      (prev, next) => {
        // Сравниваем только длину данных и тему
        return prev.data.length === next.data.length
          && prev.config.theme === next.config.theme;
      }
    );
    

    React.lazy и Suspense: код-сплиттинг

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

    import { lazy, Suspense } from 'react';
    
    // Чанк подгрузится только при первом рендере
    const Analytics = lazy(() => import('./Analytics'));
    const Editor = lazy(() => import('./Editor'));
    
    function Dashboard({ tab }) {
      return (
        <Suspense fallback={<Spinner />}>
          {tab === 'analytics' ? <Analytics /> : <Editor />}
        </Suspense>
      );
    }
    

    Suspense отображает запасной UI, пока чанк загружается. Можно вкладывать границы для гранулярного контроля состояний загрузки:

    function Page() {
      return (
        <Suspense fallback={<PageSkeleton />}>
          <Header />
          <Suspense fallback={<ContentSkeleton />}>
            <MainContent />
          </Suspense>
          <Suspense fallback={<SidebarSkeleton />}>
            <Sidebar />
          </Suspense>
        </Suspense>
      );
    }
    

    Для предзагрузки чанка по hover можно вызвать импорт заранее:

    const Modal = lazy(() => import('./Modal'));
    
    function OpenButton() {
      // Предзагружаем модалку при наведении
      const preload = () => import('./Modal');
      return <button onMouseEnter={preload}>Открыть</button>;
    }
    

    React Profiler: измерение рендеров

    Без измерений оптимизация — гадание. Profiler API позволяет программно собирать метрики рендеров в продакшене или в тестах.

    import { Profiler } from 'react';
    
    function onRender(id, phase, actualDuration, baseDuration, startTime, commitTime) {
      // actualDuration — время текущего рендера
      // baseDuration — оценка без мемоизации
      if (actualDuration > 16) {
        console.warn(`Медленный рендер ${id}: ${actualDuration.toFixed(2)}ms`);
      }
    }
    
    function App() {
      return (
        <Profiler id="ProductList" onRender={onRender}>
          <ProductList />
        </Profiler>
      );
    }
    

    В браузере используйте расширение React DevTools — вкладка Profiler показывает flame-граф рендеров, выделяет «прыгающие» компоненты и предлагает причины повторных вызовов. Запишите сценарий, найдите самые дорогие коммиты и работайте с ними в первую очередь.

    Частые ошибки

    • Мемоизация всего подряд. memo, useMemo и useCallback сами имеют цену — на сравнение и хранение. Оборачивайте только реально тяжёлые или часто перерисовываемые компоненты.
    • Нестабильные пропсы. Передача инлайн-объекта style={{ color: 'red' }} или массива items={[...]} ломает мемоизацию: ссылка меняется каждый рендер.
    • Один Suspense на весь экран. Это даёт «всё или ничего» — пользователь видит спиннер вместо частично готового интерфейса. Вкладывайте границы.
    • Оптимизация без замеров. Сначала Profiler, потом изменения. Иначе можно потратить часы на компонент, который рендерится раз в минуту.
    • Забыли про ключи в списках. Нестабильные key={index} сводят на нет любую мемоизацию дочерних элементов.

    Заключение

    React.memo, lazy, Suspense и Profiler — это базовый набор инструментов middle-разработчика для борьбы за производительность. Мемоизация убирает лишние рендеры, ленивая загрузка уменьшает бандл, Suspense управляет состояниями загрузки, а Profiler даёт объективные цифры. Главный принцип — измерять до и после, оптимизировать точечно и не превращать код в склад мемоизированных колбэков. Тогда приложение останется быстрым, а кодовая база — поддерживаемой.

    Иконка глаза374

    Комментарии

    0

    Постройте личный план изучения Nuxt - fullstack Vue фреймворк до уровня Middle — бесплатно!

    Nuxt - fullstack Vue фреймворк — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы разработки

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    бесплатно
    Подробнее
    изображение курса

    Angular

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга5.0
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажерыAI-тренажеры
    Практика в студииПрактика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее

    Похожие статьи

    Картинка поста Серверные компоненты Next.js: внутреннее устройство
    Иконка аватараАнтон
    Иконка календаря09 июля 2026
    Next.jsReactServer Components+ 2middleИконка уровня middle

    Серверные компоненты Next.js: внутреннее устройство

    Серверные компоненты Next.js выполняются только на сервере, уменьшают JS-бандл и передают данные через RSC Payload. Разбираем, как это работает изнутри.

    Иконка чипа0
    Иконка глаза92
    Иконка комментариев0
    Картинка поста GraphQL vs REST: что выбрать для API в 2026 году
    Иконка аватараАнтон
    Иконка календаря11 июля 2026
    graphqlrestapi+ 3middleИконка уровня middle

    GraphQL vs REST: что выбрать для API в 2026 году

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

    Иконка чипа0
    Иконка глаза42
    Иконка комментариев0
    Картинка поста Тестирование React-компонентов с React Testing Library
    Иконка аватараАнтон
    Иконка календаря07 июля 2026
    reacttestingreact-testing-library+ 2middleИконка уровня middle

    Тестирование React-компонентов с React Testing Library

    React Testing Library — инструмент для тестирования React-компонентов через поведение пользователя, а не детали реализации. Примеры, паттерны, частые ошибки.

    Иконка чипа0
    Иконка глаза161
    Иконка комментариев0
    Иконка чипа0