Optimizing React State and Rerenders: Lessons from Swift Delivery
How to avoid performance bottlenecks, structure your React state, and leverage hooks like useMemo and useCallback to keep your animations smooth at 60fps.
How to avoid performance bottlenecks, structure your React state, and leverage hooks like useMemo and useCallback to keep your animations smooth at 60fps.
While building Swift Delivery (a logistics and delivery platform), I noticed that as the rider list updated via live search, typing became laggy. The entire dashboard list was rerendering on every keystroke.
In this article, I outline how I diagnosed and fixed these bottlenecks.
Every time state changes, React updates the Virtual DOM and runs a reconciliation process on all children of that component. In my dashboard:
The easiest performance win is pushing state down. If only the search input needs to track typing value, wrap it in a child component. This isolates the state updates to that small inputs subtree, sparing the complex list from rerendering.
Updating lists on every key event is unnecessary. Instead, use a debouncer to defer sorting and searching:
import { useState, useEffect } from 'react';
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
}For heavy calculations (like filtering an array of riders based on geo-coordinates), wrap the calculation in useMemo:
const filteredRiders = useMemo(() => {
return riders.filter(rider => calculateDistance(userCoords, rider.coords) < 10);
}, [riders, userCoords]);Applying these techniques resolved the lag in Swift Delivery, returning the input latency to under 5ms and keeping interactive animations running at a smooth 60fps.
Showaib Hossain
Mathematics Honors & MERN Developer