DEV Community

Cover image for Building Your Own `useReducer`
Bishoy Bishai
Bishoy Bishai

Posted on • Edited on • Originally published at bishoy-bishai.github.io

Building Your Own `useReducer`

๐Ÿง  The Brain of the Team: Building Your Own useReducer

Ever felt like your component has too many "mood swings"? One useState for loading, one for error, one for data... itโ€™s a mess! In Bachata, if you try to lead five different moves at once, youโ€™re going to trip. You need one clear signal. That is useReducer.

โšฝ The "Starting Lineup" (The Problem)

Look at this. This is a team with no captain:

// Too many players, no coordination!
const [score, setScore] = useState(0);
const [isGameOver, setIsGameOver] = useState(false);
const [yellowCards, setYellowCards] = useState(0);

Enter fullscreen mode Exit fullscreen mode

If the game ends, you have to remember to call setIsGameOver(true) AND maybe reset the score. If you forget one, it's a Red Card for your app's logic.

๐Ÿ› ๏ธ Building the "Coach" (The Polyfill)

We are going to build our own version. Weโ€™ll use useState as the "legs" and useCallback to make sure the coach doesn't keep changing his mind (Stable References).

import { useState, useCallback, useRef, useEffect } from 'react';

function useOmarReducer(reducer, initialState) {
  // 1. The actual storage (The Pitch)
  const [state, setState] = useState(initialState);

  // 2. Keep the logic fresh but stable
  const reducerRef = useRef(reducer);
  useEffect(() => {
    reducerRef.current = reducer;
  }, [reducer]);

  // 3. The Dispatch (The Whistle)
  // We use useCallback so this function stays the sameโ€”"1, 2, 3, Tap!"
  const dispatch = useCallback((action) => {
    setState((prevState) => reducerRef.current(prevState, action));
  }, []);

  return [state, dispatch];
}

Enter fullscreen mode Exit fullscreen mode

Why this works:

  • useRef: Itโ€™s like a notebook. We keep the latest tactics (the reducer) there so we don't get "Stale Closures."
  • useCallback: This is key! It ensures the dispatch function doesn't change every render. If the function changed every time, it would be like a coach changing the rules every 5 minutes. No one can play like that!

๐Ÿ† Putting it on the Pitch: The Match Day

Here is how we use our custom "Coach" to manage a Football match:

const matchReducer = (state, action) => {
  switch (action.type) {
    case 'GOAL': 
      return { ...state, score: state.score + 1 };
    case 'FOUL': 
      return { ...state, yellowCards: state.yellowCards + 1 };
    case 'WHISTLE': 
      return { ...state, isGameOver: true };
    default: 
      return state;
  }
};

function FootballMatch() {
  const [match, dispatch] = useOmarReducer(matchReducer, { 
    score: 0, 
    yellowCards: 0, 
    isGameOver: false 
  });

  return (
    <div>
      <h1>Score: {match.score} โšฝ</h1>
      <button onClick={() => dispatch({ type: 'GOAL' })}>GOAAAAL!</button>
      <button onClick={() => dispatch({ type: 'FOUL' })}>Yellow Card ๐ŸŸจ</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

๐Ÿ‘Ÿ Summary of the Tactics

Term The Football/Dance Way The Code Way
Reducer The Playbook / Tactics The function that decides new state
Action The Signal (e.g., "Pass!", "Turn!") An object like { type: 'GOAL' }
Dispatch Blowing the Whistle The function that triggers the change
State The Current Score The data sitting in your component

๐Ÿ’ก Pro Tip

Never mutate the state directly! In Bachata, if you're supposed to be in position A and you suddenly teleport to B without the proper steps, the dance is ruined. In your reducer, always return a brand new object using the spread operator (...state). If you just change a property, React might not realize the "score" changed, and your UI will be stuck in the first half!

Would you like me to show you how to handle Asynchronous actions (like fetching data from a scouting API) with this setup? It gets a bit more "pro," but I know you can handle it!


โœจ Let's keep the conversation going!

If you found this interesting, I'd love for you to check out more of my work or just drop in to say hello.

โœ๏ธ Read more on my blog: bishoy-bishai.github.io

โ˜• Let's chat on LinkedIn: linkedin.com/in/bishoybishai

๐Ÿ“˜ Curious about AI?:
You can also check out my book: Surrounded by AI


Top comments (0)