Sunday, July 24, 2022

When to use useReducer over useState in react

Both useState and useReducer are react hooks to handle state management. The useState is the default choice, and useReducer should only be used when state management logic is complex.

But why useReducer is better than useState when managing complex state in react project?

For useState hook, developers call setState method returned by useState()  to update the state, setState accepts a callback method implemented by app developer, which has a single parameter of the previous state object, developer can return a new updated state based on the current state and application logic.

const [state, setState] = useState({});
setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

Assuming 5 developers work on 5 different modules of the same project, and each developer may call setState to update the shared state object of the project. The problem is some state values set by one developer may break the state set by other developers. As there is not a a center place to manage the state, and each developer can set the state based on his own logic without knowing the effect on other developer's logic.

To solve this problem, the manager of the 5 developers decide to useReducer to solve this issue, 

const [state, dispatch] = useReducer(reducer, initialState)

The manager implements the reducer method as the single method to update the state, so people can audit the state object's update history if inconsistence happens again. Each developer cannot no longer directly update the state object. In stead, if developer need to update the state, he must call the dispatch method with related parameter, the dispatch method will trigger the call of reducer method with the parameter provided by developers. The reducer method will actually update the state and also maintain the consistence of the state object.

So the key difference between useState and useReducer is useReducer provides another layer of separation, and it isolates the role of the state change requester and state change handler. Anyone can send a state change request by calling the dispatch method, but only the state change handler (the implementation of reducer method) can decide how the request is handled so as to be sure the state object is always valid.