JS Guide
HomeQuestionsSearchResources
Search

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeQuestionstesting
Prev
testing
mid
hooks

How do you test custom React hooks?

custom-hooks
renderHook
act
testing-library
Quick Answer

Use @testing-library/react's renderHook to test custom hooks in isolation. The function returns result.current with the hook's return value, and rerender to trigger updates. For hooks with state, use act() to wrap state updates.

Detailed Explanation

renderHook API:

  • renderHook(callback): Render hook in test component
  • result.current: Current return value
  • rerender(props): Re-render with new props
  • unmount(): Unmount the test component

Testing Patterns:

  • Test initial state
  • Test state updates with act()
  • Test effects and cleanup
  • Test with different inputs via rerender

Common Pitfalls:

  • Forgetting act() for state updates
  • Testing implementation instead of behavior
  • Not testing edge cases

Code Examples

Testing custom hooks
// useCounter.js
import { useState, useCallback } from 'react';

export function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  
  const increment = useCallback(() => setCount(c => c + 1), []);
  const decrement = useCallback(() => setCount(c => c - 1), []);
  const reset = useCallback(() => setCount(initialValue), [initialValue]);
  
  return { count, increment, decrement, reset };
}

// useCounter.test.js
import { renderHook, act } from '@testing-library/react';
import { useCounter } from './useCounter';

describe('useCounter', () => {
  test('initializes with default value', () => {
    const { result } = renderHook(() => useCounter());
    expect(result.current.count).toBe(0);
  });

  test('initializes with provided value', () => {
    const { result } = renderHook(() => useCounter(10));
    expect(result.current.count).toBe(10);
  });

  test('increments counter', () => {
    const { result } = renderHook(() => useCounter());
    
    act(() => {
      result.current.increment();
    });
    
    expect(result.current.count).toBe(1);
  });

  test('decrements counter', () => {
    const { result } = renderHook(() => useCounter(5));
    
    act(() => {
      result.current.decrement();
    });
    
    expect(result.current.count).toBe(4);
  });

  test('resets to initial value', () => {
    const { result } = renderHook(() => useCounter(10));
    
    act(() => {
      result.current.increment();
      result.current.increment();
    });
    expect(result.current.count).toBe(12);
    
    act(() => {
      result.current.reset();
    });
    expect(result.current.count).toBe(10);
  });
});

Resources

Testing Library - renderHook

docs

Related Questions

How do you test React components with React Testing Library?

mid
react-testing-library

How do you mock functions, modules, and API calls in Jest?

mid
mocking
Previous
What is code coverage and how do you interpret coverage reports?