Prompt
Ensure hook dependencies are minimal, stable, and follow React’s rules to prevent unnecessary re-renders and maintain predictable behavior. This includes:
-
Remove unnecessary dependencies: Only include dependencies that actually change the hook’s behavior. For example, remove
state.revalidationfrom dependency arrays when the function doesn’t need to recreate on state changes. -
Avoid writing to refs during render: Never write to
ref.currentinsideuseMemoor during component render, as this violates React’s rules and can cause unpredictable behavior with transitions. -
Use stable references: Ensure objects passed as dependencies maintain stable identity to prevent cascading re-renders.
-
Proper useEffect cleanup: Don’t return promises from
useEffectand ensure dependency arrays include all referenced values.
Example of problematic code:
// Bad - writes to ref during render in useMemo
const searchParams = useMemo(() => {
searchParamsRef.current = getSearchParamsForLocation(location.search);
return searchParamsRef.current;
}, [location.search]);
// Bad - unstable state object in dependencies
useEffect(() => {
navigate(to, { replace, state, relative });
}, [navigate, to, replace, state, relative]); // state might be unstable
Example of improved code:
// Good - use useEffect to update ref
useEffect(() => {
searchParamsRef.current = getSearchParamsForLocation(location.search);
}, [location.search]);
// Good - resolve path outside effect for stability
const path = resolveTo(to, matches, locationPathname, relative);
const jsonPath = JSON.stringify(path);
useEffect(() => {
navigate(JSON.parse(jsonPath), { replace, state, relative });
}, [navigate, jsonPath, relative, replace, state]);
This approach ensures components re-render only when necessary and maintains predictable behavior across React’s concurrent features.