It involves optimizing how your application handles asynchronous operations like data fetching, state updates, and side effects. Here are some precise strategies:
1. Use Loading States
Example:
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
fetchData().then(response => {
setData(response);
setLoading(false);
});
}, []);
return loading ? <Spinner /> : <DataComponent data={data} />;
2. Optimistic Updates
Example:
const handleLike = async (postId) => {
const previousLikes = posts[postId].likes;
setPosts(prev => ({ ...prev, [postId]: { ...prev[postId], likes: previousLikes + 1 } }));
try {
await likePost(postId);
} catch (error) {
setPosts(prev => ({ ...prev, [postId]: { ...prev[postId], likes: previousLikes } }));
}
};
3. Debounce or Throttle Input
Example with debounce:
const [query, setQuery] = useState('');
const debouncedQuery = useDebounce(query, 300);
useEffect(() => {
fetchResults(debouncedQuery);
}, [debouncedQuery]);