TIL: Optimizing React Re-renders
Today I learned about some surprising ways React components can trigger unnecessary re-renders. Here's a quick summary of what I discovered while debugging a performance issue.
The Problem
I had a component that was re-rendering way too often:
function UserList({ users }) {
const [filter, setFilter] = useState("");
const filterUsers = () => {
return users.filter(user =>
user.name.toLowerCase().includes(filter.toLowerCase())
);
};
return (
<div>
<input
value={filter}
onChange={e => setFilter(e.target.value)}
/>
{filterUsers().map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
What I Learned
- The
filterUsersfunction was being recreated on every render - Each recreation caused all
UserCardcomponents to re-render - The filter operation was running even when users hadn't changed
The Solution
function UserList({ users }) {
const [filter, setFilter] = useState("");
const filterUsers = useMemo(() => {
return users.filter(user =>
user.name.toLowerCase().includes(filter.toLowerCase())
);
}, [users, filter]);
return (
<div>
<input
value={filter}
onChange={e => setFilter(e.target.value)}
/>
{filterUsers.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Key Takeaways
- Use
useMemofor expensive computations - Watch out for function recreations
- Consider memoizing child components
- Profile before optimizing
Resources
- React DevTools Performance tab
- React docs on performance
- Chrome Performance profiler