Skip to content

API Reference

Oleg edited this page Dec 18, 2025 · 6 revisions

Complete API documentation for vitest-react-profiler.

Table of Contents


Core Functions

withProfiler(Component, displayName?)

Wraps a React component with profiling capabilities.

Signature:

function withProfiler<P>(
  Component: ComponentType<P>,
  displayName?: string
): ProfiledComponent<P>

Parameters:

  • Component - React component to profile
  • displayName (optional) - Custom name for debugging

Returns:

  • ProfiledComponent<P> - Enhanced component with profiling methods

Example:

const MyComponent = ({ title }: { title: string }) => <h1>{title}</h1>;
const ProfiledComponent = withProfiler(MyComponent, "MyComponent");

render(<ProfiledComponent title="Hello" />);

expect(ProfiledComponent).toHaveRenderedTimes(1);

renderProfiled() (Simplified)

Combines withProfiler() and render() in one call.

Signature:

function renderProfiled<P>(
  Component: ComponentType<P>,
  props: P,
  options?: RenderProfiledOptions
): RenderProfiledResult<P>

Parameters:

  • Component - React component to profile
  • props - Initial props
  • options (optional):
    • displayName?: string - Custom name for profiled component
    • renderOptions?: RenderOptions - React Testing Library options

Returns:

interface RenderProfiledResult<P> {
  component: ProfiledComponent<P>;
  rerender: (props: Partial<P>) => void;
  // All RTL utilities: container, unmount, debug, etc.
}

Example:

const { component, rerender } = renderProfiled(Counter, { value: 0 });

expect(component).toHaveRenderedTimes(1);

rerender({ value: 1 }); // Partial props merge
expect(component).toHaveRenderedTimes(2);

profileHook(hook, initialPropsOrOptions?, options?)

Profile a React hook to detect extra renders.

Signatures:

// Hook without parameters
function profileHook<TResult>(
  hook: () => TResult
): ProfileHookResult<object, TResult>;

// Hook without parameters, with options
function profileHook<TResult>(
  hook: () => TResult,
  options: ProfileHookOptions
): ProfileHookResult<object, TResult>;

// Hook with parameters
function profileHook<TProps, TResult>(
  hook: (props: TProps) => TResult,
  initialProps: TProps
): ProfileHookResult<TProps, TResult>;

// Hook with parameters and options
function profileHook<TProps, TResult>(
  hook: (props: TProps) => TResult,
  initialProps: TProps,
  options: ProfileHookOptions
): ProfileHookResult<TProps, TResult>;

Parameters:

  • hook - The hook function to profile
  • initialProps (optional) - Initial props for hooks with parameters
  • options (optional):
    • renderOptions?: RenderOptions - React Testing Library render options (wrapper, etc.)

Returns:

interface ProfileHookResult<TProps, TResult> {
  result: { readonly current: TResult };
  rerender: (newProps?: TProps) => void;
  unmount: () => void;
  ProfiledHook: ProfiledComponent<TProps>;
}

Examples:

// Basic usage
const { result, ProfiledHook } = profileHook(() => useMyHook());
expect(ProfiledHook).toHaveRenderedTimes(1);

// With parameters
const { result, ProfiledHook, rerender } = profileHook(
  ({ value }) => useCounter(value),
  { value: 1 }
);
rerender({ value: 2 });
expect(ProfiledHook).toHaveRenderedTimes(2);

// With context provider (wrapper)
const wrapper = ({ children }: { children: React.ReactNode }) => (
  <ThemeProvider>{children}</ThemeProvider>
);

const { result, ProfiledHook } = profileHook(
  () => useTheme(),
  { renderOptions: { wrapper } }
);
expect(result.current.theme).toBe('light');

// With both parameters and wrapper
const { result, ProfiledHook } = profileHook(
  (props) => useThemedCounter(props),
  { initialCount: 10 },
  { renderOptions: { wrapper: ThemeProvider } }
);

createHookProfiler(hook, initialPropsOrOptions?, options?)

Simplified API for hook profiling with built-in assertions.

Signatures:

Same as profileHook() - supports all four overloads.

Returns:

interface HookProfiler<TProps, TResult> {
  result: { readonly current: TResult };
  rerender: (newProps?: TProps) => void;
  unmount: () => void;
  ProfiledHook: ProfiledComponent<TProps>;
  expectRenderCount: (expected: number) => void;  // Built-in assertion
  getRenderCount: () => number;
  getRenderHistory: () => readonly PhaseType[];
  getLastRender: () => PhaseType | undefined;
}

Examples:

// Basic usage with built-in assertion
const profiler = createHookProfiler(() => useMyHook());
profiler.expectRenderCount(1);

// With context provider
const profiler = createHookProfiler(
  () => useTheme(),
  { renderOptions: { wrapper: ThemeProvider } }
);
profiler.expectRenderCount(1);
expect(profiler.result.current.theme).toBe('light');

Sync Matchers

toHaveRendered()

Asserts that component has rendered at least once.

expect(ProfiledComponent).toHaveRendered();
expect(ProfiledComponent).not.toHaveRendered();

toHaveRenderedTimes(count)

Asserts exact number of renders.

Parameters:

  • count: number - Expected render count
expect(ProfiledComponent).toHaveRenderedTimes(3);
expect(ProfiledComponent).not.toHaveRenderedTimes(5);

Error Message:

Expected 3 renders, but got 5 (1 mount, 4 updates)

  #1 [mount phase]
  #2 [update phase]
  #3 [update phase]
  #4 [update phase]
  #5 [update phase]

  πŸ’‘ Tip: Use Component.getRenderHistory() to inspect all render details

toHaveMountedOnce()

Asserts that component mounted exactly once.

expect(ProfiledComponent).toHaveMountedOnce();

toHaveNeverMounted()

Asserts that component never mounted.

const ProfiledComponent = withProfiler(MyComponent);
// Don't render

expect(ProfiledComponent).toHaveNeverMounted();

toHaveOnlyUpdated()

Asserts that component only updated (no mounts).

// Useful for testing child components that remount
expect(ProfiledComponent).toHaveOnlyUpdated();

toHaveRenderedWithPhase(phase)

Asserts that component rendered with specific phase.

Parameters:

  • phase: PhaseType - "mount" | "update" | "nested-update"
expect(ProfiledComponent).toHaveRenderedWithPhase("mount");
expect(ProfiledComponent).toHaveRenderedWithPhase("update");

toHaveLastRenderedWithPhase(phase)

Asserts that last render had specific phase.

rerender(<ProfiledComponent value={2} />);
expect(ProfiledComponent).toHaveLastRenderedWithPhase("update");

toMeetRenderCountBudget(budget)

Since: v1.8.0

Asserts that component renders within budget constraints. Provides DX convenience by checking multiple render constraints in a single assertion.

Parameters:

  • budget: RenderCountBudget - Budget constraints object
    • maxRenders?: number - Maximum total renders
    • maxMounts?: number - Maximum mount renders
    • maxUpdates?: number - Maximum update renders (includes nested-updates)
    • componentName?: string - Component name for error messages (optional)

Key Benefits:

  • Declarative: One assertion instead of N separate asserts
  • Readable: Express performance budget as a single object
  • Flexible: Specify only the constraints you care about

Example:

// Traditional way (verbose):
expect(ProfiledComponent).toHaveRenderedTimes(3);
expect(ProfiledComponent).toHaveMountedOnce();
expect(ProfiledComponent.getRendersByPhase('update')).toHaveLength(2);

// With budget (declarative):
expect(ProfiledComponent).toMeetRenderCountBudget({
  maxRenders: 3,
  maxMounts: 1,
  maxUpdates: 2,
  componentName: 'Dashboard'
});

// Flexible constraints - check only what matters:
expect(ProfiledComponent).toMeetRenderCountBudget({
  maxRenders: 5  // Only care about total renders
});

Error Message:

Expected Dashboard to meet render count budget:
  Total renders: 5 (budget: 3) ❌
  Mounts: 1 (budget: 1) βœ…
  Updates: 4 (budget: 2) ❌

Violations:
  Total renders exceeded: 5 > 3
  Update count exceeded: 4 > 2

Actual: 5 renders (1 mount, 4 updates)

  #1 [mount        phase]
  #2 [update       phase]
  #3 [update       phase]
  #4 [update       phase]
  #5 [update       phase]

Use Cases:

  • Performance budgets for complex components
  • Regression testing for render counts
  • CI/CD performance gates
  • Reducing test boilerplate

See Also:


notToHaveRenderLoops(options?)

Since: v1.8.0

⚠️ Diagnostic/Debugging Tool: This is NOT a regular test matcher. Use it to discover and diagnose render loop problems when tests hang or timeout. You don't write tests expecting infinite loopsβ€”this matcher helps you find them when they occur.

Asserts that component does not have suspicious render loop patterns. Detects infinite loops BEFORE hitting React's MAX_SAFE_RENDERS limit (10,000 renders).

Fills the Gap:

0 renders ────────────────────────────────────── 10,000 renders
     β”‚                                                  β”‚
     β”‚    [normal]    [suspicious]    [circuit breaker] β”‚
     β”‚        β”‚            β”‚                 β”‚          β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           ↑
                 notToHaveRenderLoops
                   detects here

vs MAX_SAFE_RENDERS:

  • MAX_SAFE_RENDERS = 10,000: Emergency stop, breaks test, doesn't help catch 5-10 extra renders
  • notToHaveRenderLoops: Detects suspicious patterns (3+ consecutive updates), provides diagnostic info

Parameters:

  • options?: RenderLoopOptions - Loop detection options
    • maxConsecutiveUpdates?: number - Max consecutive 'update' phases (default: 10)
    • maxConsecutiveNested?: number - Max consecutive 'nested-update' phases (default: same as maxConsecutiveUpdates)
    • ignoreInitialUpdates?: number - Skip first N updates (default: 0)
    • showFullHistory?: boolean - Include full render history in error (default: false)
    • componentName?: string - Component name for error messages (optional)

Key Benefits:

  • Early Detection: Catches loops at 3-10 renders, not 10,000
  • Diagnostic: Informative error messages with loop sequences
  • Configurable: Adjust thresholds for your use case

Example:

// Default threshold (10 consecutive updates)
expect(ProfiledComponent).notToHaveRenderLoops();

// Custom threshold for stricter checking
expect(ProfiledComponent).notToHaveRenderLoops({
  maxConsecutiveUpdates: 3,
  componentName: 'Counter'
});

// Ignore initialization sequence
expect(ProfiledComponent).notToHaveRenderLoops({
  ignoreInitialUpdates: 2,  // Skip first 2 updates
  maxConsecutiveUpdates: 5
});

Error Message:

Expected Counter not to have render loops, but found:
  Suspicious pattern: 11 consecutive 'update' phases (threshold: 10)

Loop sequence (renders #2-#12):
  #2  [update       phase]
  #3  [update       phase]
  #4  [update       phase]
  #5  [update       phase]
  #6  [update       phase]
  #7  [update       phase]
  #8  [update       phase]
  #9  [update       phase]
  #10 [update       phase]
  #11 [update       phase]
  ... and 1 more

Potential causes:
  - useEffect with missing/incorrect dependencies
  - setState called during render
  - Circular state updates between components

πŸ’‘ Tip: Use Counter.getRenderHistory() to inspect full history

When to Use (Diagnostic Scenarios):

  1. Test hangs during development

    • Your test freezes/hangs β†’ Add notToHaveRenderLoops() β†’ Get diagnostic message showing the loop
    • Example: useEffect without dependencies causing infinite updates
  2. CI timeout without clear error

    • Test times out in CI with no useful message β†’ Add this matcher β†’ Get informative error instead of timeout
    • Helps identify the exact render sequence causing the problem
  3. Debugging complex component performance

    • Suspect unnecessary re-renders in production β†’ Add temporarily to tests β†’ Identify cascade update chains
    • Remove after fixing the issue
  4. Code review / PR validation

    • Reviewer suspects potential loop β†’ Add matcher to verify β†’ Proves component is safe

When NOT to Use:

  • ❌ Don't add to every test "just in case"
  • ❌ Don't use as a regular assertion like toHaveRenderedTimes()
  • ❌ Not a replacement for proper useEffect dependency arrays

This matcher is a diagnostic tool for problem discovery, not a standard testing practice.

Common Patterns Detected:

// ❌ BAD: useEffect without dependencies
useEffect(() => {
  if (count < 100) {
    setCount(c => c + 1);  // Infinite loop!
  }
}); // Missing [count] dependency

// ❌ BAD: Cascade updates
useEffect(() => {
  if (step1 === 1) setStep2(1);
}, [step1]);
useEffect(() => {
  if (step2 === 1) setStep3(1);
}, [step2]);

Real-World Diagnostic Workflow:

// Step 1: Test hangs - you don't know why
it('should update counter', () => {
  render(<Counter />);
  // Test hangs here... ❓
});

// Step 2: Add diagnostic matcher
it('should update counter', () => {
  const Profiled = withProfiler(Counter);
  render(<Profiled />);

  // Add this to diagnose the hang
  expect(Profiled).notToHaveRenderLoops({
    maxConsecutiveUpdates: 5
  });
  // Now you get: "Suspicious pattern: 11 consecutive 'update' phases"
  // β†’ Points to useEffect infinite loop
});

// Step 3: Fix the bug
function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(c => c + 1);
  }, []); // βœ… Added dependency array - loop fixed!

  return <div>{count}</div>;
}

// Step 4: Remove diagnostic matcher (optional)
// Once bug is fixed, you can remove the matcher
// or keep it as a regression guard

See Also:


Snapshot API

Since: v1.10.0 | Extended: v1.11.0

The Snapshot API provides methods for creating render baselines and measuring render deltas. This is the primary tool for testing React optimizations like React.memo, useCallback, and ensuring single renders per user action.

πŸ‘‰ See Snapshot API for full documentation.

Quick reference:

Method/Matcher Description
snapshot() Create baseline for render counting
getRendersSinceSnapshot() Get renders since baseline
toHaveRerenderedOnce() Assert exactly 1 rerender
toNotHaveRerendered() Assert no rerenders
toHaveRerendered() Assert at least 1 rerender (v1.11.0)
toHaveRerendered(n) Assert exact N rerenders (v1.11.0)
toEventuallyRerender() Wait for async rerender (v1.11.0)
toEventuallyRerenderTimes(n) Wait for exact N async rerenders (v1.11.0)

Basic example:

const ProfiledComponent = withProfiler(Counter);
render(<ProfiledComponent />);

ProfiledComponent.snapshot();
fireEvent.click(screen.getByText('Increment'));

expect(ProfiledComponent).toHaveRerenderedOnce();

Async Utilities

Event-based utilities for waiting on renders (no polling overhead).

waitForRenders(component, count, options?)

Wait for exact render count.

Signature:

function waitForRenders<P>(
  component: ProfiledComponent<P>,
  count: number,
  options?: WaitOptions
): Promise<void>

Parameters:

  • component - Profiled component
  • count - Expected render count
  • options.timeout? - Max wait time in ms (default: 1000)

Example:

const AsyncComponent = () => {
  const [count, setCount] = useState(0);
  useEffect(() => {
    setTimeout(() => setCount(1), 100);
  }, []);
  return <div>{count}</div>;
};

const Profiled = withProfiler(AsyncComponent);
render(<Profiled />);

// Wait for mount + async update
await waitForRenders(Profiled, 2);

expect(Profiled.getRenderCount()).toBe(2);

waitForMinimumRenders(component, minCount, options?)

Wait for at least N renders.

// Wait for at least 2 renders
await waitForMinimumRenders(ProfiledComponent, 2);

expect(ProfiledComponent.getRenderCount()).toBeGreaterThanOrEqual(2);

waitForPhase(component, phase, options?)

Wait for specific render phase.

Parameters:

  • phase: PhaseType - "mount" | "update" | "nested-update"
const { rerender } = render(<ProfiledComponent />);

rerender(<ProfiledComponent value={2} />);
await waitForPhase(ProfiledComponent, "update");

expect(ProfiledComponent.getRendersByPhase("update").length).toBeGreaterThan(0);

waitForStabilization(options?): Promise<StabilizationResult>

Since: v1.12.0

Wait for component to "stabilize" - when renders stop for a specified debounce period. Uses debounce pattern: resolves after debounceMs with no renders.

Signature:

function waitForStabilization(options?: StabilizationOptions): Promise<StabilizationResult>

interface StabilizationOptions {
  debounceMs?: number;  // Default: 50 - Time without renders to consider stable
  timeout?: number;     // Default: 1000 - Max wait time before timeout error
}

interface StabilizationResult {
  renderCount: number;    // Number of renders tracked during wait
  lastPhase?: PhaseType;  // Last render phase (undefined if no renders)
}

Use Cases:

  • Virtualized lists - Wait for scroll to complete and list to stabilize
  • Debounced search - Wait for search input to settle
  • Animations - Wait for animation frames to complete
  • Data loading cascades - Wait for dependent data fetches to resolve

Example:

const VirtualList = ({ items }) => {
  // Complex virtualization with many renders during scroll
  return <div>{items.map(item => <Item key={item.id} {...item} />)}</div>;
};

const ProfiledList = withProfiler(VirtualList);
const { rerender } = render(<ProfiledList items={items} />);

// Start waiting for stabilization
const promise = ProfiledList.waitForStabilization({
  debounceMs: 50,   // Wait 50ms after last render
  timeout: 2000     // Fail after 2s if still rendering
});

// Simulate rapid scroll (many rerenders)
for (let i = 0; i < 10; i++) {
  rerender(<ProfiledList items={items} scrollTop={i * 100} />);
}

// Wait for list to stabilize
const result = await promise;

console.log(`List stabilized after ${result.renderCount} renders`);
expect(result.lastPhase).toBe("update");

Error Handling:

// Timeout error when component never stabilizes
try {
  await ProfiledComponent.waitForStabilization({ timeout: 100 });
} catch (error) {
  // "StabilizationTimeoutError: Component did not stabilize within 100ms (15 renders)"
}

// Validation error when debounceMs >= timeout
await ProfiledComponent.waitForStabilization({
  debounceMs: 200,
  timeout: 100  // Error: debounceMs must be less than timeout
});

Important: Start waiting BEFORE triggering renders (same pattern as waitForNextRender):

// βœ… Correct: Start waiting first
const promise = ProfiledComponent.waitForStabilization();
triggerManyRenders();
await promise;

// ❌ Wrong: Waiting after renders - may resolve immediately
triggerManyRenders();
await ProfiledComponent.waitForStabilization(); // May miss renders!

Async Matchers

Event-based matchers that wait for conditions.

toEventuallyRenderTimes(count, options?)

Assert component eventually renders exact number of times.

// Default 1000ms timeout
await expect(ProfiledComponent).toEventuallyRenderTimes(3);

// Custom timeout
await expect(ProfiledComponent).toEventuallyRenderTimes(5, { timeout: 2000 });

toEventuallyRenderAtLeast(minCount, options?)

Assert component eventually renders at least N times.

await expect(ProfiledComponent).toEventuallyRenderAtLeast(2);

toEventuallyReachPhase(phase, options?)

Assert component eventually reaches specific phase.

await expect(ProfiledComponent).toEventuallyReachPhase("update");
await expect(ProfiledComponent).toEventuallyReachPhase("mount", { timeout: 500 });

toEventuallyStabilize(options?)

Since: v1.12.0

Assert component eventually stabilizes (stops rendering for debounceMs period).

Signature:

interface StabilizationOptions {
  debounceMs?: number;  // Default: 50
  timeout?: number;     // Default: 1000
}

Example:

const SearchResults = ({ query }) => {
  const [results, setResults] = useState([]);
  useEffect(() => {
    // Debounced API call triggers multiple renders
    debouncedSearch(query).then(setResults);
  }, [query]);
  return <ul>{results.map(r => <li key={r.id}>{r.name}</li>)}</ul>;
};

const ProfiledSearch = withProfiler(SearchResults);
render(<ProfiledSearch query="react" />);

// Wait for search to stabilize
await expect(ProfiledSearch).toEventuallyStabilize({
  debounceMs: 100,
  timeout: 2000
});

// Component is now stable - verify results
expect(screen.getAllByRole('listitem')).toHaveLength(10);

Validation Errors:

The matcher returns pass: false with helpful messages for invalid options:

// debounceMs must be positive
await expect(ProfiledComponent).toEventuallyStabilize({ debounceMs: 0 });
// "Expected debounceMs to be a positive number, received 0"

// debounceMs must be less than timeout
await expect(ProfiledComponent).toEventuallyStabilize({
  debounceMs: 100,
  timeout: 50
});
// "Expected debounceMs (100) to be less than timeout (50)"

See Also:


ProfiledComponent API

Methods available on profiled components.

getRenderCount(): number

Returns total number of renders.

const count = ProfiledComponent.getRenderCount();

getRenderHistory(): readonly PhaseType[]

Returns array of all render phases (frozen).

const history = ProfiledComponent.getRenderHistory();
// ["mount", "update", "update"]

getLastRender(): PhaseType | undefined

Returns phase of last render.

const lastPhase = ProfiledComponent.getLastRender();
// "update"

getRenderAt(index): PhaseType | undefined

Returns phase at specific index (0-based).

const firstRender = ProfiledComponent.getRenderAt(0);
// "mount"

getRendersByPhase(phase): readonly PhaseType[]

Returns all renders matching specific phase.

const updates = ProfiledComponent.getRendersByPhase("update");
// ["update", "update", "update"]

hasMounted(): boolean

Returns true if component has mounted.

if (ProfiledComponent.hasMounted()) {
  // Component mounted
}

onRender(callback): UnsubscribeFn

Subscribe to render events (real-time notifications).

Signature:

function onRender(
  callback: (info: RenderEventInfo) => void
): () => void

Parameters:

  • callback - Function called on each render
    • info.count - Total render count
    • info.phase - Current phase
    • info.history - All render phases (read-only)

Returns:

  • Unsubscribe function

Example:

const renders: RenderEventInfo[] = [];

const unsubscribe = ProfiledComponent.onRender((info) => {
  renders.push(info);
  console.log(`Render #${info.count}: ${info.phase}`);
});

// Trigger renders...

unsubscribe(); // Cleanup

waitForNextRender(options?): Promise<RenderEventInfo>

Wait for next component render.

Important: Create promise BEFORE triggering action!

// βœ… Correct: Start waiting first
const promise = ProfiledComponent.waitForNextRender({ timeout: 1000 });

// Then trigger action
fireEvent.click(button);

// Then await
const info = await promise;
expect(info.phase).toBe("update");
// ❌ Wrong: Action before waiting
fireEvent.click(button);
const info = await ProfiledComponent.waitForNextRender(); // May miss render!

snapshot(): void

Since: v1.10.0

Creates a baseline for render counting. See Snapshot API for full documentation.

ProfiledComponent.snapshot();

getRendersSinceSnapshot(): number

Since: v1.10.0

Returns the number of renders since the last snapshot() call. See Snapshot API for full documentation.

const delta = ProfiledComponent.getRendersSinceSnapshot();

Utility Functions

clearRegistry()

Manually clears the component registry. This function is exported for advanced use cases where automatic cleanup needs to be controlled manually.

Signature:

function clearRegistry(): void

Import:

import { clearRegistry } from 'vitest-react-profiler';

Usage:

import { clearRegistry } from 'vitest-react-profiler';

// Disable auto-setup and use manual cleanup
describe('Manual cleanup tests', () => {
  afterEach(() => {
    clearRegistry(); // Manual cleanup
  });
});

When to use:

  • ❌ NOT needed in 99% of cases - automatic cleanup via auto-setup.ts handles this
  • βœ… Advanced scenarios with custom test lifecycle
  • βœ… Integration with non-standard test runners
  • βœ… Debugging registry state

Important Notes:

  • The library automatically cleans up between tests using Vitest's afterEach() and afterAll() hooks
  • Manual cleanup is rarely needed - only use when you have specific requirements
  • See Best Practices for more information on automatic cleanup

Related:


TypeScript Types

ProfiledComponent<P>

interface ProfiledComponent<P> extends ComponentType<P> {
  getRenderCount(): number;
  getRenderHistory(): readonly PhaseType[];
  getLastRender(): PhaseType | undefined;
  getRenderAt(index: number): PhaseType | undefined;
  getRendersByPhase(phase: PhaseType): readonly PhaseType[];
  hasMounted(): boolean;
  onRender(callback: (info: RenderEventInfo) => void): () => void;
  waitForNextRender(options?: WaitOptions): Promise<RenderEventInfo>;
  snapshot(): void;                        // Since v1.10.0
  getRendersSinceSnapshot(): number;       // Since v1.10.0
  readonly OriginalComponent: ComponentType<P>;
}

RenderEventInfo

interface RenderEventInfo {
  count: number; // Total render count
  phase: PhaseType; // "mount" | "update"
  readonly history: readonly PhaseType[]; // All phases
}

PhaseType

type PhaseType = "mount" | "update" | "nested-update";

WaitOptions

interface WaitOptions {
  timeout?: number; // Max wait time in ms (default: 1000)
}

ProfileHookOptions

interface ProfileHookOptions {
  /**
   * React Testing Library render options.
   * Most commonly used for wrapping the hook in a context provider.
   */
  renderOptions?: RenderOptions;
}

Example:

const options: ProfileHookOptions = {
  renderOptions: {
    wrapper: ({ children }) => <MyProvider>{children}</MyProvider>
  }
};

const { result } = profileHook(() => useMyHook(), options);

See Also

Clone this wiki locally