Хук не можна викликати поза компонентом. 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