Review React code for unnecessary useEffect usage based on react.dev guidelines.
Arguments:
- $ARGUMENTS: Optional scope to analyze (default: current git changes). Examples: "diff to main", "src/components/", "whole codebase"
Before reviewing, internalize these principles:
-
Transforming data for rendering - Calculate during render instead
// Bad const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(firstName + ' ' + lastName); }, [firstName, lastName]); // Good const fullName = firstName + ' ' + lastName;
-
Caching expensive calculations - Use
useMemoinstead// Bad useEffect(() => { setFilteredList(items.filter(predicate)); }, [items]); // Good const filteredList = useMemo(() => items.filter(predicate), [items]);
-
Resetting state when a prop changes - Use a
keyinstead// Bad useEffect(() => { setComment(''); }, [userId]); // Good <Profile userId={userId} key={userId} />
-
Adjusting state when a prop changes - Calculate during render
// Bad useEffect(() => { setSelection(null); }, [items]); // Good const [prevItems, setPrevItems] = useState(items); if (items !== prevItems) { setPrevItems(items); setSelection(null); }
-
Sharing logic between event handlers - Extract to a function
// Bad useEffect(() => { if (product.isInCart) { showNotification(`Added ${product.name} to cart!`); } }, [product]); // Good function buyProduct() { addToCart(product); showNotification(`Added ${product.name} to cart!`); }
-
Sending POST requests on form submit - Handle in the event handler
// Bad useEffect(() => { if (submitted) { post('/api/submit', { data }); } }, [submitted]); // Good function handleSubmit() { post('/api/submit', { data }); }
-
Chains of computations - Calculate in render or event handlers
-
Initializing the application - Do it outside the component or use a flag
// Bad useEffect(() => { loadDataFromLocalStorage(); }, []); // Good (outside component) if (typeof window !== 'undefined') { loadDataFromLocalStorage(); }
-
Notifying parent components about state changes - Pass callbacks instead
-
Passing data to parent - Lift state up instead
- Synchronizing with external systems (DOM, network, third-party widgets)
- Setting up subscriptions
- Fetching data (though consider React Query, SWR, or RSC instead)
- Measuring DOM elements after render
-
Determine scope: Use $ARGUMENTS if provided, otherwise analyze uncommitted changes via
git diff -
Find useEffect usage: Search for
useEffectcalls in the target scope -
Analyze each useEffect:
- What is it doing?
- Does it match any of the anti-patterns above?
- Is it truly synchronizing with an external system?
-
Report findings: For each unnecessary useEffect, explain:
- The file and line number
- Why it's unnecessary
- The recommended fix with code example
-
Apply fixes: After showing proposed changes, ask if the user wants them applied
- Be conservative: if unsure whether an effect is necessary, explain the tradeoff rather than removing it
- Consider the broader context (data fetching libraries, framework patterns)
- Some effects that look unnecessary may be intentional for specific reasons
- Prioritize readability and maintainability over premature optimization