In React, performance optimization at the component level is mainly about preventing unnecessary re-renders and avoiding expensive operations on every render. React is efficient by default, but improper state management, prop handling, and rendering patterns can slow down your application. Hereβs a practical explanation of key optimization techniques with examples.
React.memo: React.memo is a higher-order component that prevents a functional component from re-rendering if its props have not changed. It performs a shallow comparison of props.
import React from 'react';
function UserCard({ name }) {
console.log('UserCard rendered');
return <h2>{name}</h2>;
}
export default React.memo(UserCard);
In this example, UserCard will only re-render if the name prop changes. This is useful for presentational components that receive stable props.
useCallback: useCallback is used to memoize functions so they are not recreated on every render. This is especially helpful when passing functions to child components wrapped with React.memo.
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
Here, handleClick will keep the same reference between renders, preventing unnecessary re-renders in memoized child components.
useMemo: useMemo is used to memoize expensive calculations so they only run when their dependencies change.
import React, { useState, useMemo } from 'react';
function FilteredList({ items }) {
const [query, setQuery] = useState('');
const filteredItems = useMemo(() => {
console.log('Filtering items...');
return items.filter(item => item.includes(query));
}, [items, query]);
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
Avoid Inline Objects and Functions: Inline objects and functions create new references on every render, which can cause unnecessary re-renders in child components.
Instead of:
Use:
const style = { color: 'red' };
List Rendering Optimization: When rendering lists, always use a stable and unique key.
Prefer:
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
Using stable keys helps React correctly identify which items have changed, added, or removed.
Lazy Loading Components: Use React.lazy and Suspense to load components only when needed.
import React, { Suspense } from 'react';
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
In summary, React performance optimization is about reducing unnecessary renders and expensive computations. Use React.memo for components, useCallback for functions, useMemo for calculations, avoid unstable references, and structure your components thoughtfully.
Thank you for reading.
Happy coding!
Top comments (0)