Spec-Zone.ru › React 18

<StrictMode>

<StrictMode> позволяет находить распространённые ошибки в ваших компонентах на ранней стадии разработки.

<StrictMode>
  <App />
</StrictMode>
  • Ссылка
    • <StrictMode>
  • Использование
    • Включение режима Strict Mode для всего приложения
    • Включение режима Strict Mode для части приложения
    • Исправление ошибок, обнаруженных при двойном рендеринге во время разработки
    • Исправление ошибок, обнаруженных при повторном выполнении эффектов во время разработки
    • Исправление предупреждений об устаревших API, включенных режимом Strict Mode

Ссылка

<StrictMode>

Используйте StrictMode для включения дополнительных поведенческих особенностей и предупреждений для дерева компонентов внутри:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

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

См. больше примеров ниже.

Режим Strict Mode включает следующие поведенческие особенности, используемые только в режиме разработки:

  • Ваши компоненты будут перерисовываться дополнительно один раз, чтобы найти ошибки, вызванные нечистым рендерингом.
  • Ваши компоненты будут повторно выполнять эффекты дополнительно один раз, чтобы найти ошибки, вызванные отсутствием очистки эффектов.
  • Ваши компоненты будут проверяться на использование устаревших API.

Свойства

StrictMode не принимает свойства.

Ограничения

  • Нет способа отказаться от режима Strict Mode внутри дерева, обернутого в <StrictMode>. Это даёт уверенность в том, что все компоненты внутри <StrictMode> проверяются. Если две команды, работающие над продуктом, не согласны с тем, считают ли они проверки полезными, им необходимо либо прийти к общему мнению, либо опустить <StrictMode> ниже в дереве.

Использование

Включение режима Strict Mode для всего приложения

Режим Strict Mode включает дополнительные проверки, выполняемые только в режиме разработки, для всего дерева компонентов внутри компонента <StrictMode>. Эти проверки помогают найти распространённые ошибки в компонентах на ранней стадии разработки.

Чтобы включить режим Strict Mode для всего приложения, оберните свой корневой компонент <StrictMode> при его рендеринге:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

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

Рекомендуется обернуть всё приложение в Strict Mode, особенно для вновь созданных приложений. Если вы используете фреймворк, который вызывает createRoot за вас, ознакомьтесь с его документацией, чтобы узнать, как включить Strict Mode.

Хотя проверки режима Strict Mode выполняются только в режиме разработки, они помогают найти ошибки, которые уже существуют в вашем коде, но могут быть сложно воспроизводимыми в режиме производства. Режим Strict Mode позволяет исправить ошибки до того, как пользователи их обнаружат.

Примечание

Режим Strict Mode включает следующие проверки в режиме разработки:

  • Ваши компоненты будут перерисовываться дополнительно один раз, чтобы найти ошибки, вызванные нечистым рендерингом.
  • Ваши компоненты будут повторно выполнять эффекты дополнительно один раз, чтобы найти ошибки, вызванные отсутствием очистки эффектов.
  • Ваши компоненты будут проверяться на использование устаревших API.

Все эти проверки выполняются только в режиме разработки и не влияют на сборку для производства.


Включение режима Strict Mode для части приложения

Вы также можете включить режим Strict Mode для любой части своего приложения:

import { StrictMode } from 'react';

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

В этом примере проверки режима Strict Mode не будут выполняться для компонентов Header и Footer. Однако они будут выполняться для Sidebar и Content, а также для всех компонентов внутри них, независимо от глубины вложенности.


Исправление ошибок, обнаруженных при двойном рендеринге во время разработки

React предполагает, что каждый ваш компонент — чистая функция. Это означает, что компоненты React, которые вы пишете, всегда должны возвращать одинаковый JSX при одинаковых входных данных (свойства, состояние и контекст).

Компоненты, нарушающие это правило, ведут себя непредсказуемо и вызывают ошибки. Чтобы помочь вам найти случайно нечистые фрагменты кода, Strict Mode выполняет некоторые из ваших функций (только те, которые должны быть чистыми) дважды в режиме разработки. Это включает в себя:

  • Тело функции вашего компонента (только логика верхнего уровня, поэтому это не включает код внутри обработчиков событий)
  • Функции, которые вы передаёте в useState, set функции, useMemo или useReducer
  • Некоторые методы класса компонента, такие как constructor, render, shouldComponentUpdate (см. весь список)

Если функция чистая, её повторное выполнение не изменяет её поведение, потому что чистая функция каждый раз производит одинаковый результат. Однако, если функция нечистая (например, она изменяет полученные данные), её повторное выполнение, как правило, заметно (вот что делает её нечистой!). Это помогает вам обнаружить и исправить ошибку на ранней стадии.

Вот пример, иллюстрирующий, как двойной рендеринг в режиме Strict Mode помогает найти ошибки на ранней стадии.

Этот StoryTray компонент принимает массив stories и добавляет в конец ещё один элемент «Создать историю»:

export default function StoryTray({ stories }) {
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul>
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

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

Эта ошибка станет более заметной, если компонент StoryTray перерисовывается многократно. Например, давайте сделаем, чтобы компонент StoryTray перерисовывался с другим цветом фона при наведении на него:

import { useState } from 'react';

export default function StoryTray({ stories }) {
  const [isHover, setIsHover] = useState(false);
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul
      onPointerEnter={() => setIsHover(true)}
      onPointerLeave={() => setIsHover(false)}
      style={{
        backgroundColor: isHover ? '#ddd' : '#fff'
      }}
    >
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Обратите внимание, как каждый раз при наведении на компонент StoryTray «Создать историю» снова добавляется в список. Целью кода было добавить его один раз в конце. Но StoryTray напрямую изменяет массив stories из свойств. Каждый раз, когда StoryTray перерисовывается, он добавляет «Создать историю» в конец того же массива. Другими словами, StoryTray — не чистая функция — её многократное выполнение приводит к различным результатам.

Чтобы исправить эту проблему, можно скопировать массив и изменить эту копию вместо оригинального:

export default function StoryTray({ stories }) {
  const items = stories.slice(); // Clone the array
  // ✅ Good: Pushing into a new array
  items.push({ id: 'create', label: 'Create Story' });

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

Теперь давайте обернём исходный (ошибочный) код в <StrictMode>:

export default function StoryTray({ stories }) {
  const items = stories;
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul>
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Режим Strict Mode всегда вызывает вашу функцию рендеринга дважды, поэтому вы сразу увидите ошибку («Создать историю» появляется дважды). Это позволяет заметить такие ошибки на ранней стадии процесса. Когда вы исправляете свой компонент, чтобы он рендерился в режиме Strict Mode, вы также устраняете многие потенциальные будущие ошибки в режиме производства, такие как функция наведения указателя, описанная ранее:

import { useState } from 'react';

export default function StoryTray({ stories }) {
  const [isHover, setIsHover] = useState(false);
  const items = stories.slice(); // Clone the array
  items.push({ id: 'create', label: 'Create Story' });
  return (
    <ul
      onPointerEnter={() => setIsHover(true)}
      onPointerLeave={() => setIsHover(false)}
      style={{
        backgroundColor: isHover ? '#ddd' : '#fff'
      }}
    >
      {items.map(story => (
        <li key={story.id}>
          {story.label}
        </li>
      ))}
    </ul>
  );
}

Без режима Strict Mode ошибку легко было пропустить, пока вы не добавили больше перерисовок. Режим Strict Mode заставил ту же ошибку появиться сразу. Режим Strict Mode помогает найти ошибки до того, как вы отправите их своей команде и пользователям.

Дополнительная информация о том, как сохранять компоненты чистыми.

Примечание

Если у вас установлены React DevTools, все вызовы console.log во время второго вызова рендеринга будут отображаться слегка затемнёнными. React DevTools также предлагает настройку (по умолчанию выключена) для их полного подавления.


Исправление ошибок, обнаруженных при повторном выполнении эффектов во время разработки

Режим Strict Mode также может помочь найти ошибки в эффектах.

Каждый эффект имеет код настройки и может иметь код очистки. Обычно React вызывает настройку, когда компонент монтируется (добавляется на экран), и вызывает очистку, когда компонент размонтируется (удаляется с экрана). Затем React повторно вызывает очистку и настройку, если его зависимости изменились с момента последнего рендеринга.

Когда режим Strict Mode включён, React также будет выполнять дополнительный цикл настройки+очистки для каждого эффекта в режиме разработки. Это может показаться неожиданным, но это помогает выявить скрытые ошибки, которые сложно поймать вручную.

Вот пример, иллюстрирующий, как повторное выполнение эффектов в режиме Strict Mode помогает найти ошибки на ранней стадии.

Рассмотрим этот пример, который подключает компонент к чату:

import { createRoot } from 'react-dom/client';
import './styles.css';

import App from './App';

const root = createRoot(document.getElementById("root"));
root.render(<App />);

В этом коде есть проблема, но она может не быть сразу очевидной.

Чтобы сделать проблему более очевидной, давайте реализуем функцию. В примере ниже roomId не жёстко задано. Вместо этого пользователь может выбрать roomId чата, к которому он хочет подключиться, из раскрывающегося списка. Нажмите «Открыть чат», а затем выберите разные чаты один за другим. Отслеживайте количество активных подключений в консоли:

import { createRoot } from 'react-dom/client';
import './styles.css';

import App from './App';

const root = createRoot(document.getElementById("root"));
root.render(<App />);

Вы заметите, что количество открытых подключений постоянно увеличивается. В реальном приложении это привело бы к проблемам с производительностью и сетью. Проблема в том, что ваш эффект не имеет функции очистки:

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]);

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

Теперь давайте обернём исходный (ошибочный) код в <StrictMode>:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './styles.css';

import App from './App';

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

В режиме Strict Mode вы сразу видите проблему (количество активных подключений увеличивается до 2). Режим Strict Mode выполняет дополнительный цикл настройки+очистки для каждого эффекта. Этот эффект не имеет логики очистки, поэтому он создаёт дополнительное подключение, но не уничтожает его. Это подсказка о том, что вам нужна функция очистки.

Режим Strict Mode позволяет заметить такие ошибки на ранней стадии. Когда вы исправляете свой эффект, добавив функцию очистки в режиме Strict Mode, вы также устраняете многие потенциальные будущие ошибки в режиме производства, такие как раскрывающийся список, описанный ранее:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './styles.css';

import App from './App';

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

Обратите внимание, как количество активных подключений в консоли больше не увеличивается.

Без строгого режима было легко пропустить необходимость очистки вашего эффекта. Используя настройка → очистка → настройка вместо настройки для вашего эффекта в разработке, Строгий режим позволил более заметно увидеть отсутствующую логику очистки.

Подробнее об реализации очистки эффекта.


Исправление предупреждений об устаревших API, включенных в строгий режим

React предупреждает, если какой-либо компонент где-либо внутри <StrictMode> дерева использует один из этих устаревших API:

  • findDOMNode. См. альтернативы.
  • UNSAFE_ методы жизненного цикла класса, такие как UNSAFE_componentWillMount. См. альтернативы.
  • Устаревший контекст (childContextTypes, contextTypes и getChildContext). См. альтернативы.
  • Устаревшие строковые ссылки (this.refs). См. альтернативы.

Эти API в основном используются в более старых классовых компонентах, поэтому они редко встречаются в современных приложениях.

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://18.react.dev/reference/react/StrictMode

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API