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ПлюсPurpleMax
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

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

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развитияВопросы для собеседований
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • PurpleSchool — курсы программирования онлайн
    • Подписка
    • 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 даёт объективные цифры. Главный принцип — измерять до и после, оптимизировать точечно и не превращать код в склад мемоизированных колбэков. Тогда приложение останется быстрым, а кодовая база — поддерживаемой.

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

    Комментарии

    0

    Постройте личный план изучения CSS Flexbox - полный курс и практика его использования до уровня Middle — бесплатно!

    CSS Flexbox - полный курс и практика его использования — часть карты развития Frontend

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

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

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

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

    Основы JavaScript

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

    Продвинутый JavaScript

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

    TypeScript с нуля

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

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

    Картинка поста Профессиональное выгорание программиста: признаки и как с ним бороться
    Иконка аватараАнтон
    Иконка календаря28 октября 2026
    выгораниепродуктивностьsoft skills+ 2middleИконка уровня middle

    Профессиональное выгорание программиста: признаки и как с ним бороться

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

    Иконка чипа0
    Иконка глаза53
    Иконка комментариев0
    Картинка поста Neovim + avante.nvim с Claude из России: настройка
    Иконка аватараАнтон
    Иконка календаря27 октября 2026
    AI-инструментыAnthropicразработкаmiddleИконка уровня middle

    Neovim + avante.nvim с Claude из России: настройка

    avante.nvim — плагин для Neovim, который добавляет ИИ-ассистента в стиле Cursor: боковую панель с чатом по коду, правки выделенного фрагмента и применение изменений прямо в буфер. С Claude он работает через провайдер `claude`, но из России напрямую не подключится: API Anthropic отклоняет российские адреса, а ключ оплачивается зарубежной картой. Решение — указать в конфиге плагина свой адрес API (`endpoint`) и ключ AI для кода от PurpleSchool с оплатой в рублях. Ниже — установка через lazy.nvim, актуальный конфиг, горячие клавиши и частые ошибки.

    Иконка чипа0
    Иконка глаза90
    Иконка комментариев0
    Картинка поста OpenCode: пользовательские провайдеры недоступны — что делать
    Иконка аватараАнтон
    Иконка календаря26 октября 2026
    AI-инструментыapiразработкаjuniorИконка уровня junior

    OpenCode: пользовательские провайдеры недоступны — что делать

    Ошибка «Пользовательские провайдеры недоступны на этом сервере» (в английском интерфейсе — «Custom providers are unavailable on this server») появляется в OpenCode Desktop и веб-интерфейсе OpenCode, когда вы сохраняете своего провайдера через «Настройки → Провайдеры → Пользовательский провайдер». Это ошибка самого OpenCode, а не вашего ключа, сервера или региона: в версиях 2.0.x форма сохранения не подключена к серверу и выдаёт эту ошибку при любых введённых данных. VPN и смена ключа не помогут. Решение — описать провайдера в файле `opencode.json`: так он работает и в Desktop, и в терминальной версии. Ниже — что именно сломано, готовые конфиги для Claude, GPT и Qwen и что делать, если модели не появились.

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