React Performance Optimization Guide
react
performance
optimization
Use Production Build
Always use the production build of React in production environments:
npm run build
Code-Splitting with React.lazy and Suspense
import React, { Suspense, lazy } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
);
}
Memoization
React.memo for Functional Components
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
useMemo for Expensive Calculations
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback for Callbacks
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
Virtualization for Long Lists
Use react-window or react-virtualized for rendering large lists:
import { FixedSizeList as List } from 'react-window';
function Row({ index, style }) {
return <div style={style}>Row {index}</div>;
}
function Example({ items }) {
return (
<List
height={150}
itemCount={items.length}
itemSize={35}
width={300}
>
{Row}
</List>
);
}
Avoid Inline Function Definitions in Renders
Instead of:
<button onClick={() => handleClick(id)}>Click me</button>
Do:
const handleClick = useCallback((id) => {
// handle click
}, []);
// In render:
<button onClick={() => handleClick(id)}>Click me</button>
Use Fragment to Avoid Additional HTML Element Wrappers
import React, { Fragment } from 'react';
function ListItem({ item }) {
return (
<Fragment>
<dt>{item.term}</dt>
<dd>{item.description}</dd>
</Fragment>
);
}
Avoid Using Index as Key for Map
Instead of:
{items.map((item, index) => (
<Component key={index} {...item} />
))}
Do:
{items.map((item) => (
<Component key={item.id} {...item} />
))}
Debouncing and Throttling
Use lodash's debounce or throttle for handling frequent event callbacks:
import { debounce } from 'lodash';
const debouncedHandleChange = debounce(handleChange, 300);
function handleChange(e) {
// Handle the event
}
// In render:
<input onChange={debouncedHandleChange} />
Use Web Workers for CPU Intensive Tasks
// worker.js
self.addEventListener('message', (e) => {
const result = expensiveOperation(e.data);
self.postMessage(result);
});
// In your React component
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = (e) => {
setResult(e.data);
};
Remember, always measure performance before and after optimization to ensure your changes are having the desired effect. Use React DevTools Profiler and Chrome DevTools Performance tab for detailed analysis.