DEV Community

Rae Liu
Rae Liu

Posted on

React Hooks - useState and useReducer cheat sheet - for developers who don't know Redux

I was having trouble to understand useReducer because I don't have Redux background. So I wrote this article to explain it to myself, and I hope it can help you as well.

Learn useState first

If you know how useState works, then you can skip this section, and I am going to compare useReducer to useState.

useState example (reactjs.org)


  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

const [count, setCount] = useState(0);

  • useState(0): It passes the initial state (in this case, it is 0), and returns an array with 2 elements - count and setCount.
  • count: new state
  • setCount: the function that uses to change the state value. It is like this.setState() in class based component.

Compare to useReducer

useReducer is used for complicated state situation.
For example, I want to add one more button to decrease counter.

Here is the code by using useState

useState example (reactjs.org)

 const [count, setCount] = useState(0);

  return (
    <div>
      {count}
      <button onClick={() => setCount(count + 1)}>
        +
      </button>
      <button onClick={() => setCount(count - 1)}>
        -
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

We are going to move count+1 and count -1 to a FUNCTION by using useReducer

const [count, setCount] = useReducer(FUNCTION, {count: 0})
Enter fullscreen mode Exit fullscreen mode

In useReducer, we call count as state, setCount as dispatch, and FUNCTION is reducer

So it looks like this -

const [state, dispatch] = useReducer(reducer, {count: 0})
Enter fullscreen mode Exit fullscreen mode

MDN explains pretty well what is Array.prototype.reduce() is. It may help you to understand what is the reducer funciton in useReducer.

Next, we are going to write the reducer function

reducer function passes 2 parameters

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}
Enter fullscreen mode Exit fullscreen mode

state: the current state
action: if I want to change state, then I call dispatch function. In this case, the first element is type, refer to action.type.

For example, I call dispatch({type: 'increment'}), then count will be + 1.

<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
Enter fullscreen mode Exit fullscreen mode

Full codes -

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, {count: 0});
  return (
      {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Hope it will help you! ❤️

Top comments (1)

Collapse
 
sendy profile image
Sandeep

Wow, useReducer definitely looks cleaner than writing separate handlers for different state updates. Thanks for sharing :)