Simple and complete React hooks testing utilities that encourage good testing practices.
npx @tessl/cli install tessl/npm-testing-library--react-hooks@8.0.0React Hooks Testing Library provides simple and complete testing utilities for React hooks, encouraging good testing practices. It allows you to test custom hooks in isolation without creating wrapper components, handling the complexities of running hooks within function components while providing utilities for updating inputs and retrieving outputs.
npm install --save-dev @testing-library/react-hooksimport { renderHook, act } from "@testing-library/react-hooks";For specific renderer environments:
// DOM environment (default auto-detected)
import { renderHook, act } from "@testing-library/react-hooks/dom";
// React Native environment
import { renderHook, act } from "@testing-library/react-hooks/native";
// Server-side rendering environment
import { renderHook, act } from "@testing-library/react-hooks/server";
// Pure environment (no auto-setup)
import { renderHook, act } from "@testing-library/react-hooks/pure";CommonJS:
const { renderHook, act } = require("@testing-library/react-hooks");import { renderHook, act } from "@testing-library/react-hooks";
import { useState } from "react";
// Test a simple custom hook
function useCounter(initialCount = 0) {
const [count, setCount] = useState(initialCount);
const increment = () => setCount(prev => prev + 1);
const decrement = () => setCount(prev => prev - 1);
return { count, increment, decrement };
}
test("useCounter hook", () => {
const { result } = renderHook(() => useCounter(5));
// Check initial value
expect(result.current.count).toBe(5);
// Test increment
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(6);
// Test decrement
act(() => {
result.current.decrement();
});
expect(result.current.count).toBe(5);
});React Hooks Testing Library is built around several key components:
Core functionality for rendering and testing React hooks in isolation. The renderHook function creates a test harness that runs your hook within a proper React component context.
function renderHook<TProps, TResult>(
callback: (props: TProps) => TResult,
options?: RenderHookOptions<TProps>
): RenderHookResult<TProps, TResult>;
interface RenderHookOptions<TProps> {
initialProps?: TProps;
wrapper?: React.ComponentType<TProps>;
}State update wrapping utilities that ensure proper timing and batching of React updates during testing. Essential for testing hooks that perform state updates or side effects.
function act(callback: () => void | undefined): void;
function act(callback: () => Promise<void | undefined>): Promise<undefined>;Utilities for testing asynchronous hook behavior, including waiting for updates, value changes, and condition fulfillment.
interface AsyncUtils {
waitFor(callback: () => boolean | void, options?: WaitForOptions): Promise<void>;
waitForValueToChange(selector: () => unknown, options?: WaitForValueToChangeOptions): Promise<void>;
waitForNextUpdate(options?: WaitForNextUpdateOptions): Promise<void>;
}
interface WaitForOptions {
interval?: number | false;
timeout?: number | false;
}Cleanup utilities for managing test teardown, both automatic and manual cleanup of rendered hooks and associated resources.
function cleanup(): Promise<void>;
function addCleanup(callback: CleanupCallback): () => void;
function removeCleanup(callback: CleanupCallback): void;
type CleanupCallback = () => Promise<void> | void;Error suppression and handling utilities for testing error scenarios and managing console output during tests.
function suppressErrorOutput(): () => void;Server-specific rendering capabilities for testing hooks in SSR environments with hydration support. Only available when using the server renderer.
interface ServerRenderHookResult<TProps, TValue> extends RenderHookResult<TProps, TValue> {
hydrate(): void;
}When using @testing-library/react-hooks/server, the renderHook function returns a result that includes a hydrate() method for testing server-side rendering scenarios.
interface RenderHookResult<TProps, TValue> {
result: {
readonly current: TValue;
readonly all: Array<TValue | Error>;
readonly error?: Error;
};
rerender: (newProps?: TProps) => void;
unmount: () => void;
waitFor: (callback: () => boolean | void, options?: WaitForOptions) => Promise<void>;
waitForValueToChange: (selector: () => unknown, options?: WaitForValueToChangeOptions) => Promise<void>;
waitForNextUpdate: (options?: WaitForNextUpdateOptions) => Promise<void>;
}
interface WrapperComponent<TProps> extends React.ComponentType<TProps> {}
type Act = {
(callback: () => Promise<void | undefined>): Promise<undefined>;
(callback: () => void | undefined): void;
}
interface WaitForOptions {
interval?: number | false;
timeout?: number | false;
}
interface WaitForValueToChangeOptions {
interval?: number | false;
timeout?: number | false;
}
interface WaitForNextUpdateOptions {
timeout?: number | false;
}
class TimeoutError extends Error {
constructor(util: Function, timeout: number);
}