Spec-Zone.ru › React 18

act

act — это вспомогательный инструмент для применения ожидающих обновлений React перед выполнением утверждений.

await act(async actFn)

Чтобы подготовить компонент к утверждениям, оберните код, отображающий его и выполняющий обновления, в вызов await act(). Это позволит вашему тесту работать аналогично тому, как React работает в браузере.

Примечание

Использование act() напрямую может показаться избыточным. Чтобы избежать излишнего кода, вы можете использовать библиотеку, такую как React Testing Library, вспомогательные функции которой обернуты act().

  • Ссылка
    • await act(async actFn)
  • Использование
    • Отображение компонентов в тестах
    • Отправка событий в тестах
  • Устранение неполадок
    • Ошибка: «Текущая тестовая среда не настроена для поддержки act» (…)

Ссылка

await act(async actFn)

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

Название act происходит от шаблона Arrange-Act-Assert.

it ('renders with button disabled', async () => {
  await act(async () => {
    root.render(<TestComponent />)
  });
  expect(container.querySelector('button')).toBeDisabled();
});

Примечание

Рекомендуется использовать act с await и функцией async. Хотя синхронная версия работает во многих случаях, она не работает во всех и из-за способа внутренней планировки обновлений React трудно предсказать, когда можно использовать синхронную версию.

В будущем синхронная версия будет устаревать и удалена.

Параметры

  • async actFn: Асинхронная функция, которая оборачивает отрисовку или взаимодействия с тестируемыми компонентами. Любые обновления, инициированные внутри actFn, добавляются в внутреннюю очередь act, которая затем сливается для обработки и применения любых изменений в DOM. Поскольку это асинхронная функция, React также выполнит любой код, пересекающий асинхронную границу, и осуществит слив всех запланированных обновлений.

Возвращаемое значение

act ничего не возвращает.

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

При тестировании компонента вы можете использовать act для выполнения утверждений о его выводе.

Например, предположим, что у нас есть этот Counter компонент, примеры использования ниже показывают, как его протестировать:

function Counter() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(prev => prev + 1);
  }

  useEffect(() => {
    document.title = `You clicked ${this.state.count} times`;
  }, [count]);

  return (
    <div>
      <p>You clicked {this.state.count} times</p>
      <button onClick={this.handleClick}>
        Click me
      </button>
    </div>
  )
}

Отображение компонентов в тестах

Для тестирования вывода компонента оберните отрисовку в act():

import {act} from 'react';
import ReactDOMClient from 'react-dom/client';
import Counter from './Counter';

it('can render and update a counter', async () => {
  container = document.createElement('div');
  document.body.appendChild(container);
  
  // ✅ Render the component inside act().
  await act(() => {
    ReactDOMClient.createRoot(container).render(<Counter />);
  });
  
  const button = container.querySelector('button');
  const label = container.querySelector('p');
  expect(label.textContent).toBe('You clicked 0 times');
  expect(document.title).toBe('You clicked 0 times');
});

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

Использование act гарантирует, что все обновления будут применены перед выполнением утверждений.

Отправка событий в тестах

Для тестирования событий оберните отправку события в act():

import {act} from 'react';
import ReactDOMClient from 'react-dom/client';
import Counter from './Counter';

it.only('can render and update a counter', async () => {
  const container = document.createElement('div');
  document.body.appendChild(container);
  
  await act( async () => {
    ReactDOMClient.createRoot(container).render(<Counter />);
  });
  
  // ✅ Dispatch the event inside act().
  await act(async () => {
    button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
  });

  const button = container.querySelector('button');
  const label = container.querySelector('p');
  expect(label.textContent).toBe('You clicked 1 times');
  expect(document.title).toBe('You clicked 1 times');
});

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

Возможная проблема

Не забывайте, что отправка событий DOM работает только тогда, когда контейнер DOM добавлен в документ. Вы можете использовать библиотеку, такую как React Testing Library, чтобы сократить объем кода.

Устранение неполадок

Ошибка: «Текущая тестовая среда не настроена для поддержки act» (…)

Использование act требует настройки global.IS_REACT_ACT_ENVIRONMENT=true в вашей тестовой среде. Это необходимо для того, чтобы act использовался только в правильной среде.

Если вы не установите глобальную переменную, вы увидите ошибку такого типа:

Консоль
Предупреждение: Текущая тестовая среда не настроена для поддержки act(…)

Для исправления добавьте это в свой глобальный файл настройки для тестов React:

global.IS_REACT_ACT_ENVIRONMENT=true

Примечание

В фреймворках тестирования, таких как React Testing Library, IS_REACT_ACT_ENVIRONMENT уже установлено для вас.

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

Spec-Zone.ru

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