Skip to content
    SeaCode
    Learning tracksCode ArenaWorkshops & EventsInstructors
    Log inSign up
    ⚛React

    Components and JSX

    • Why React?
    • JSX rules
    • Props
    • Rendering lists and keys
    • Conditional rendering

    State and events

    • Handling events
    • useState: a component's memory
    • Objects and arrays in state
    • Forms and controlled inputs
    • Lifting state up

    Effects and essential hooks

    • useEffect
    • Fetching data
    • useRef
    • Context: data for the whole tree
    • useReducer

    Professional React

    • Writing your own hooks
    • Performance: memo, useMemo and useCallback
    • Suspense and error boundaries
    • What's new in React 19
    • Thinking in React
    • Project: a complete to-do app
    React

    Professional React · Lesson 17 of 21

    Performance: memo, useMemo and useCallback

    When components re-render, and when memoization actually helps.

    11 minutes2 games

    Rule: when a component re-renders, all its children re-render too, even if their props didn't change. Usually that's fast and fine. But for an expensive child (a long list, a chart) you can prevent it with:

    • memo(Component): skip re-rendering when props are the same.
    • useMemo(() => calc, deps): remember an expensive calculation's result.
    • useCallback(fn, deps): keep the same function, so memo isn't defeated.
    React
    const renders = { list: 0 }
    
    const CourseList = memo(function CourseList({ items, onPick }) {
      renders.list++
      console.log("CourseList rendered", renders.list, "times")
      return <ul>{items.map((c) => <li key={c} onClick={() => onPick(c)}>{c}</li>)}</ul>
    })
    
    function App() {
      const [query, setQuery] = useState("")
      const [clicks, setClicks] = useState(0)
      const all = ["HTML", "CSS", "JavaScript", "Python", "React", "SQL", "C++"]
    
      const items = useMemo(() => all.filter((c) => c.toLowerCase().includes(query.toLowerCase())), [query])
      const onPick = useCallback((c) => console.log("picked", c), [])
    
      return (
        <div>
          <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Filter" />
          <button onClick={() => setClicks(clicks + 1)}>Unrelated click ({clicks})</button>
          <CourseList items={items} onPick={onPick} />
        </div>
      )
    }

    Press "Unrelated click" a few times and watch the console: CourseList doesn't re-render because items and onPick are the same values. Remove useMemo or useCallback and every render creates a new array or function, so memo sees different props and re-renders.

    App re-renders

    Same items and onPick references?

    yes → memo skips CourseList

    no → CourseList re-renders

    Important

    Don't wrap everything in useMemo and useCallback: they have a cost, make code harder to read, and usually don't matter. Measure first with the React DevTools Profiler and optimize only what's actually slow. Simpler fixes often win: move state down into the component that needs it, or pass the expensive part as children. The new React Compiler does this memoization automatically.

    Quick question

    A memo component receives style={{ color: "red" }} from its parent. Does it re-render when the parent does?

    Interview question

    What's the difference between useMemo and useCallback, and when do you use them?

    Exercise

    expensive is slow. Compute it with useMemo so it depends on n only, not on theme. The page shows Result: 55 and Computed 1 times, even after the checker presses Theme twice.

    The page should show:
    Result: 55
    Computed 1 times
    Theme
    React
    let computed = 0
    function expensive(n) {
      computed++
      let sum = 0
      for (let i = 1; i <= n; i++) sum += i
      return sum
    }
    
    function App() {
      const [n] = useState(10)
      const [theme, setTheme] = useState("light")
      const result = expensive(n)
      return (
        <div>
          <p>Result: {result}</p>
          <p>Computed {computed} times</p>
          <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Theme</button>
        </div>
      )
    }

    Learn more from

    • react.dev: memoreact.dev
    • react.dev: useMemoreact.dev
    • react.dev: useCallbackreact.dev
    • react.dev: React Compilerreact.dev
    • Overreacted: Before you memo()overreacted.io
    • Kent C. Dodds: When to useMemo and useCallbackkentcdodds.com

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousWriting your own hooksNextSuspense and error boundaries
    SeaCode

    Learn to code for real, online or at our branch in front of Cairo University, Giza.

    Learn

    • All courses
    • Interactive tutorials
    • Interview practice problems
    • Mock interview
    • Learning tracks
    • Code Arena
    • Workshops & Events
    • Knowledge library
    • Team projects

    Your account

    • Log in
    • Sign up
    • Learning plan
    • Certificates
    • Site map

    Contact us

    • WhatsApp
    • 010 9094 1104
    • In front of Cairo University, Giza

    © 2026 SeaCode. All rights reserved.