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

    Effects and essential hooks · Lesson 15 of 21

    useReducer

    All state changes in one function, with clear names.

    10 minutes2 games

    When state grows and its changes multiply and scatter across many handlers, useReducer gathers them in one place. Instead of saying "set this value", you say what happened (dispatch({ type: "added" })), and a function called a reducer decides the new state.

    React
    function cartReducer(state, action) {
      switch (action.type) {
        case "added":
          return { ...state, items: [...state.items, action.item] }
        case "removed":
          return { ...state, items: state.items.filter((i) => i.id !== action.id) }
        case "couponApplied":
          return { ...state, discount: 0.1 }
        default:
          throw new Error("Unknown action " + action.type)
      }
    }
    
    function App() {
      const [cart, dispatch] = useReducer(cartReducer, { items: [], discount: 0 })
      const total = cart.items.reduce((s, i) => s + i.price, 0) * (1 - cart.discount)
    
      return (
        <div>
          <button onClick={() => dispatch({ type: "added", item: { id: Date.now(), title: "React", price: 600 } })}>Add React</button>
          <button onClick={() => dispatch({ type: "couponApplied" })}>Apply coupon</button>
          <ul>
            {cart.items.map((i) => (
              <li key={i.id}>{i.title} <button onClick={() => dispatch({ type: "removed", id: i.id })}>x</button></li>
            ))}
          </ul>
          <p>Total: {total} EGP</p>
        </div>
      )
    }

    Button: dispatch({ type: "added", item })

    React calls cartReducer(state, action)

    The reducer returns a new state

    re-render

    Important

    A reducer must be pure: the same state and action always give the same result, with no fetches, timers or Math.random(), and without mutating the old state. That's what makes it easy to test: a plain function you feed input and check output.

    Spot the bug

    This reducer breaks React's rules. Which line?

    Interview question

    When would you choose useReducer over useState?

    Exercise

    Finish quizReducer: the answered action carries correct (true/false). If correct, add one to score; either way add one to asked. The checker presses Right twice and Wrong once, so it should show Score: 2 / 3.

    The page should show:
    Score: 2 / 3
    Right Wrong
    React
    function quizReducer(state, action) {
      return state
    }
    
    function App() {
      const [s, dispatch] = useReducer(quizReducer, { score: 0, asked: 0 })
      return (
        <div>
          <p>Score: {s.score} / {s.asked}</p>
          <button className="ok" onClick={() => dispatch({ type: "answered", correct: true })}>Right</button>
          <button className="no" onClick={() => dispatch({ type: "answered", correct: false })}>Wrong</button>
        </div>
      )
    }

    Learn more from

    • react.dev: Extracting state logic into a reducerreact.dev
    • react.dev: useReducer referencereact.dev
    • Redux docs: Reducersredux.js.org

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousContext: data for the whole treeNextWriting your own hooks
    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.