# Strategic Memoization React is fast by default. Over-memoizing (`useMemo`, `useCallback`) can sometimes hurt performance more than it helps due to the cost of checking dependencies and allocating memory for the memoized functions/values. ## Why it matters - **Too little:** Expensive calculations block the main thread. - **Too much:** Code becomes harder to read (`useCallback` hell) and the overhead of memoization outweighs the re-render cost of simple components. ## Incorrect Memoizing everything blindly. ```tsx // Incorrect: Primitive values and simple objects don't need memoization const value = useMemo(() => 42, []); const style = useMemo(() => ({ color: 'red' }), []); // Incorrect: Inline functions on lightweight HTML elements are fine const handleClick = useCallback(() => { console.log('clicked'); }, []); return ; ``` ## Correct Memoize only when beneficial. ### 1. Referential Equality for Dependencies When a value/function is used in a `useEffect` dependency array, stability matters. ```tsx const params = useMemo(() => ({ id: userId }), [userId]); useEffect(() => { api.fetch(params); }, [params]); // params must be stable to avoid infinite loops ``` ### 2. Expensive Calculations Heavy synchronous work (e.g., filtering a 5,000 item list). ```tsx const sortedList = useMemo(() => { return largeArray.filter(item => item.active).sort((a, b) => a.value - b.value); }, [largeArray]); ``` ### 3. Passing to Optimized Children (`React.memo`) If a child component is wrapped in `React.memo`, passing a new function reference every render will break the optimization. ```tsx const HandleChange = useCallback((val) => { setValue(val); }, []); // HeavyComponent is wrapped in React.memo, so it needs stable props return ; ```