Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як тестувати власні хуки через renderHook?

Хук не можна викликати поза компонентом. renderHook рендерить тестовий компонент, що викликає хук, і дає доступ до його результату.

import { renderHook, act } from '@testing-library/react';

function useCounter(initial = 0) {
  const [count, setCount] = useState(initial);
  return { count, increment: () => setCount((c) => c + 1) };
}

test('збільшує лічильник', () => {
  const { result } = renderHook(() => useCounter(5));

  expect(result.current.count).toBe(5);

  act(() => result.current.increment());

  expect(result.current.count).toBe(6);
});

Ключові моменти:

  • result.current - значення, повернене хуком при останньому рендері. Не можна зберегти const { count } = result.current на початку - значення застаріє;
  • act потрібен для виклику функцій, що оновлюють стан, - так оновлення застосується до наступної перевірки;
  • зміна аргументів - через rerender:
const { result, rerender } = renderHook(({ id }) => useUser(id), { initialProps: { id: 1 } });
rerender({ id: 2 });
  • демонтування - unmount(), щоб перевірити очищення (відписка, скасування запиту).

Асинхронні хуки - з waitFor:

const { result } = renderHook(() => useVacancies());
await waitFor(() => expect(result.current.status).toBe('success'));

Хуки, що потребують провайдерів (контекст, роутер, клієнт TanStack Query) - опція wrapper:

const wrapper = ({ children }) => (
  <QueryClientProvider client={new QueryClient()}>{children}</QueryClientProvider>
);
const { result } = renderHook(() => useVacancies(), { wrapper });

Коли тестувати хук окремо, а коли через компонент:

  • окремо - хук зі складною логікою, що використовується в багатьох місцях (форматування, синхронізація з URL, машина станів);
  • через компонент - хук, що існує заради одного компонента. Тест компонента перевіряє поведінку, яку бачить користувач, і не ламається, якщо логіку переставити між хуком і компонентом.

Історія: раніше renderHook був в окремому пакеті @testing-library/react-hooks; для React 18+ він вбудований у @testing-library/react, а старий пакет не підтримується.

Докладніше в документації: React Testing Library: renderHook

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання