React Scan
React Scan is a performance monitoring tool for React applications designed to automatically detect re-render issues and potential performance bottlenecks. Unlike React's built-in `Profiler` or other tools like `Why Did You Render?`, `react-scan` aims to provide simple visual cues and requires minimal to no code changes for integration. It offers a portable API accessible via npm, CDN script tags, or a command-line interface, making it versatile for various development workflows across different React frameworks. The package is currently at version 0.5.3 and maintains an active development cycle with a moderate release cadence, though previous versions noted a period of slower releases. Key features include highlighting re-rendering components, providing notifications for performance issues, and offering a persistent, draggable toolbar for inspection.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'scan') or similar errors when `scan()` is called in production.
cause Using the default `import { scan } from 'react-scan';` in a production build or non-development environment where it's not intended to run, or where its internal environment checks fail.fixFor production or universal usage (where `scan()` needs to be active in all environments), explicitly use the subpath import: `import { scan } from 'react-scan/all-environments';`. -
React Scan is constantly notifying about FPS drops or re-renders during hot module reloading, even when there's no actual performance issue.
cause Older versions of `react-scan` (prior to v0.3.3) incorrectly identified hot reloading events as performance degradation, leading to false-positive notifications.fixUpgrade `react-scan` to version `0.3.3` or a later version. This update includes a fix that prevents the tool from misinterpreting hot reloads. -
The React Scan toolbar is obstructing my view and I cannot easily minimize or hide it, especially in versions before 0.4.0.
cause Prior to version 0.4.0, the `react-scan` toolbar had limited options for being hidden or minimized, making it intrusive for some workflows.fixUpgrade `react-scan` to version `0.4.0` or higher. This version introduced the ability to 'throw' the toolbar off the edge of the screen, which hides it and persists across reloads.
Warnings
- breaking The 'state change timeline' feature was temporarily removed in version 0.3.0 due to a bug in the 'what's changed' view. It may be re-introduced in a future release.
- gotcha Prior to version 0.3.3, `react-scan` incorrectly attributed hot module reloading events as FPS drops, leading to false-positive performance notifications in the toolbar.
- breaking Calling the default `scan()` export in a production build or non-development environment prior to v0.3.6 could lead to errors being logged. This was fixed by introducing a specific import path.
- gotcha Version 0.4.0 introduced a significant UI/UX change, allowing the React Scan toolbar to be 'thrown' off the page to hide it. This state persists across reloads.
- breaking A memory leak was identified and fixed in version 0.4.3, specifically when interacting with the page many times while `react-scan` was active.
Install
-
npm install react-scan -
yarn add react-scan -
pnpm add react-scan
Imports
- scan
const scan = require('react-scan').scan;import { scan } from 'react-scan'; - scan (all-environments)
import { scan } from 'react-scan';import { scan } from 'react-scan/all-environments'; - Options
type Options = any;
import { Options } from 'react-scan';
Quickstart
import { scan, Options } from 'react-scan';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
// Define options for React Scan, typically enabling it only in development.
const scanOptions: Options = {
enabled: process.env.NODE_ENV === 'development', // Crucial for conditional activation
debug: false, // Set to true for verbose logging
// You can add more options like filters or thresholds here.
};
// Initialize React Scan. It's best practice to call it once early in your app lifecycle.
// Ensure this runs only client-side if your environment is universal (SSR/SSG).
if (typeof window !== 'undefined') {
scan(scanOptions);
}
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('App component mounted or re-rendered');
});
return (
<div>
<h1>React Scan Basic Example</h1>
<p>Current count: {count}</p>
<button onClick={() => setCount(prev => prev + 1)}>
Increment Count
</button>
<ChildComponent value={count} />
</div>
);
}
function ChildComponent({ value }: { value: number }) {
// This component will re-render whenever its 'value' prop changes.
// React Scan will highlight it and report its renders if enabled.
return (
<p>Child component showing value: {value}</p>
);
}
// Render your application using ReactDOM.
const rootElement = document.getElementById('root');
if (rootElement) {
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
} else {
console.error("Root element not found! Ensure an element with id='root' exists in your HTML.");
}