Hack Frontend Community

React.StrictMode

Что такое StrictMode?

React.StrictMode — это инструмент для выявления потенциальных проблем в приложении. Он активирует дополнительные проверки и предупреждения только в режиме разработки.

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Production:

StrictMode не влияет на production-сборку. Все проверки работают только в development.


Для чего нужен?

StrictMode помогает:

  1. Выявлять компоненты с небезопасными методами жизненного цикла
  2. Предупреждать об использовании устаревшего API
  3. Обнаруживать неожиданные побочные эффекты
  4. Предупреждать об использовании устаревшего context API
  5. Обеспечивать повторное использование состояния (React 18+)

Двойной рендер

StrictMode намеренно вызывает функции дважды, чтобы помочь найти побочные эффекты:

function Counter() {
  const [count, setCount] = useState(0);
  
  console.log('Render'); // В StrictMode выведется дважды!

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
}

Вызываются дважды:

  • Тело функционального компонента
  • Функции внутри useState, useMemo, useReducer
  • Функция-конструктор (для классовых компонентов)
  • Методы render, shouldComponentUpdate, getDerivedStateFromProps

Выявление побочных эффектов

Проблемный код

let globalCounter = 0;

function Component() {
  // Побочный эффект вне useEffect!
  globalCounter++; // В StrictMode увеличится дважды
  
  return <div>Counter: {globalCounter}</div>;
}

Правильный код

let globalCounter = 0;

function Component() {
  useEffect(() => {
    // Побочные эффекты в useEffect
    globalCounter++;
    
    return () => {
      globalCounter--; // Cleanup
    };
  }, []);
  
  return <div>Counter: {globalCounter}</div>;
}

Обнаружение устаревших методов

StrictMode предупредит об использовании устаревших методов жизненного цикла:

class MyComponent extends React.Component {
  componentWillMount() {
    // Предупреждение: устаревший метод
  }

  componentWillReceiveProps(nextProps) {
    // Предупреждение: устаревший метод
  }

  componentWillUpdate(nextProps, nextState) {
    // Предупреждение: устаревший метод
  }

  render() {
    return <div>Hello</div>;
  }
}

Правильные альтернативы

class MyComponent extends React.Component {
  static getDerivedStateFromProps(props, state) {
    // Вместо componentWillReceiveProps и componentWillUpdate
    return null;
  }

  componentDidMount() {
    // Вместо componentWillMount
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Для получения информации перед обновлением DOM
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // Работа с snapshot
  }

  render() {
    return <div>Hello</div>;
  }
}

Обнаружение устаревшего context API

Устаревший способ (предупреждение)

class Parent extends React.Component {
  static childContextTypes = {
    color: PropTypes.string
  };

  getChildContext() {
    return { color: 'purple' };
  }

  render() {
    return <Child />;
  }
}

Современный способ

const ThemeContext = React.createContext('light');

function Parent() {
  return (
    <ThemeContext.Provider value="dark">
      <Child />
    </ThemeContext.Provider>
  );
}

function Child() {
  const theme = useContext(ThemeContext);
  return <div>Theme: {theme}</div>;
}

Использование в части приложения

Можно применять StrictMode только к определённым компонентам:

function App() {
  return (
    <div>
      <Header />
      
      <React.StrictMode>
        <Sidebar />
        <Content />
      </React.StrictMode>
      
      <Footer />
    </div>
  );
}

Header и Footer не будут проверяться, только Sidebar и Content.


React 18: повторное использование состояния

В React 18 StrictMode моделирует размонтирование и повторное монтирование компонентов:

function Component() {
  useEffect(() => {
    console.log('Mount');
    
    return () => {
      console.log('Unmount');
    };
  }, []);

  return <div>Hello</div>;
}

В StrictMode выведет:

Mount
Unmount
Mount

Это помогает убедиться, что компонент правильно очищает ресурсы при размонтировании.


Проблемы с консольными логами

Проблема

function Component() {
  console.log('Render'); // Выводится дважды в StrictMode
  
  return <div>Hello</div>;
}

Решение 1: Игнорировать

Помните, что двойной вызов только в development. В production будет один вызов.

Решение 2: React DevTools

React DevTools автоматически убирает дубликаты логов от StrictMode:

// Установите React DevTools расширение
// Дубликаты логов будут скрыты автоматически

Решение 3: Обернуть в условие

function Component() {
  if (process.env.NODE_ENV === 'development') {
    // Логи только в development, но всё равно дважды
    console.log('Render');
  }
  
  return <div>Hello</div>;
}

Когда отключать StrictMode?

Не рекомендуется отключать

StrictMode помогает писать качественный код. Но есть случаи:

При интеграции со сторонними библиотеками

Если библиотека вызывает предупреждения, которые вы не можете исправить:

function App() {
  return (
    <div>
      <React.StrictMode>
        <MyApp />
      </React.StrictMode>
      
      {/* Сторонняя библиотека без StrictMode */}
      <ThirdPartyComponent />
    </div>
  );
}

При отладке в консоли

Если двойные логи мешают отладке, временно отключите:

// Временно для отладки
// <React.StrictMode>
  <App />
// </React.StrictMode>

Не забудьте вернуть StrictMode после отладки!


Best Practices

Используйте с самого начала

Добавляйте StrictMode при создании проекта:

// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Исправляйте предупреждения

Не игнорируйте предупреждения StrictMode. Они указывают на реальные проблемы.

Используйте в CI/CD

Убедитесь, что тесты запускаются с StrictMode:

// setupTests.js
import { render } from '@testing-library/react';

function renderWithStrictMode(ui) {
  return render(
    <React.StrictMode>
      {ui}
    </React.StrictMode>
  );
}

Частые вопросы

Влияет ли StrictMode на производительность?

Нет, в production StrictMode полностью отключается. Все проверки работают только в development.

Почему мой код выполняется дважды?

Это намеренное поведение StrictMode для выявления побочных эффектов. В production код будет выполнен один раз.

Нужно ли оборачивать всё приложение?

Рекомендуется оборачивать всё приложение, но можно применять выборочно к проблемным частям.


Вывод

React.StrictMode:

  • Инструмент для выявления проблем в development
  • Не влияет на production
  • Намеренно вызывает функции дважды
  • Предупреждает об устаревших методах и API
  • Помогает писать чистый код без побочных эффектов
  • Подготавливает к будущим версиям React
  • Рекомендуется использовать во всех проектах

На собеседовании:

Важно уметь:

  • Объяснить, что такое StrictMode и для чего он нужен
  • Рассказать, почему код выполняется дважды
  • Перечислить, какие проблемы помогает выявить
  • Объяснить, что StrictMode не влияет на production
  • Привести примеры правильной работы с побочными эффектами