Skip to main content

Overview

The onRender() function allows you to hook into render events for a specific component type. This is useful for custom performance monitoring, debugging, or analytics.

Signature

onRender(
  type: unknown,
  callback: (fiber: Fiber, renders: Array<Render>) => void
): void

Parameters

type
unknown
required
The component type to monitor. This is typically a component function or class reference.
callback
(fiber: Fiber, renders: Array<Render>) => void
required
Callback function invoked when the specified component renders.

Returns

void - This function does not return a value.

Usage

Monitor Specific Component

import { onRender } from 'react-scan';
import { MyComponent } from './MyComponent';

onRender(MyComponent, (fiber, renders) => {
  console.log('MyComponent rendered:', renders);
});

Track Render Performance

import { onRender } from 'react-scan';
import { ExpensiveComponent } from './ExpensiveComponent';

onRender(ExpensiveComponent, (fiber, renders) => {
  renders.forEach(render => {
    if (render.time && render.time > 16) {
      console.warn(`Slow render detected: ${render.time}ms`);
    }
  });
});

Log Render Changes

import { onRender } from 'react-scan';
import { UserProfile } from './UserProfile';

onRender(UserProfile, (fiber, renders) => {
  renders.forEach(render => {
    console.log(`${render.componentName} render #${render.count}`);
    console.log('Changes:', render.changes);
  });
});

Detect Unnecessary Renders

import { onRender, setOptions } from 'react-scan';
import { MyComponent } from './MyComponent';

// Enable unnecessary render tracking
setOptions({ trackUnnecessaryRenders: true });

onRender(MyComponent, (fiber, renders) => {
  renders.forEach(render => {
    if (render.unnecessary) {
      console.warn('Unnecessary render detected in', render.componentName);
      console.log('Changes:', render.changes);
    }
  });
});

Send Analytics

import { onRender } from 'react-scan';
import { CriticalComponent } from './CriticalComponent';

onRender(CriticalComponent, (fiber, renders) => {
  renders.forEach(render => {
    // Send performance data to analytics service
    analytics.track('component_render', {
      component: render.componentName,
      time: render.time,
      count: render.count,
      fps: render.fps,
    });
  });
});

Monitor Multiple Components

import { onRender } from 'react-scan';
import { ComponentA, ComponentB, ComponentC } from './components';

const components = [ComponentA, ComponentB, ComponentC];

components.forEach(Component => {
  onRender(Component, (fiber, renders) => {
    console.log(`${Component.name} rendered`);
  });
});

Behavior

  • Multiple onRender calls for the same component type will chain callbacks - all callbacks will be invoked
  • The callback is invoked after the component renders but before the browser paints
  • Callbacks are stored globally and persist until the page reloads
  • The fiber parameter provides low-level access to React’s internal fiber tree
Be cautious when using the fiber parameter. React’s internal fiber structure is not a public API and may change between React versions.

Performance Considerations

  • Keep callback functions lightweight to avoid impacting render performance
  • Avoid heavy computations or synchronous operations in callbacks
  • Be mindful when logging frequently-rendering components
// ❌ Avoid heavy operations
onRender(MyComponent, (fiber, renders) => {
  // Heavy serialization on every render
  const serialized = JSON.stringify(fiber, null, 2);
  console.log(serialized);
});

// ✅ Better: Keep it lightweight
onRender(MyComponent, (fiber, renders) => {
  console.log('Render count:', renders[0]?.count);
});

See Also

  • Options - Configure global render callbacks
  • setOptions() - Set global onRender callback
  • Types - Type definitions for Fiber and Render

Build docs developers (and LLMs) love