Search⌘ K
AI Features

Reducer Basics

Explore the basics of reducers in React by understanding how functions manage state and actions within TypeScript. This lesson helps you grasp the process of defining reducers, using action types, and integrating with React’s useReducer hook to simplify state management effectively.

At its most fundamental level, a reducer is simply a function that takes two arguments: the current state and an object representing an action that has occurred. The reducer returns the new state based on that action.

 A diagram showing how a reducer works
A diagram showing how a reducer works

Working of reducer

The following code is regular JavaScript, but it could easily be converted to TypeScript by adding any types to state and action:

Javascript (babel-node)
export const incrementAction = { type: 'Increment' };
export const decrementAction = { type: 'Decrement' };
export const counterReducer = (state, action) => {
if (action.type === 'Increment') {
return { count: state.count + 1 };
}
if (action.type === 'Decrement') {
return { count: state.count - 1 };
}
return state;
};
let state = { count: 1 };
state = counterReducer(state, incrementAction);
state = counterReducer(state, incrementAction);
state = counterReducer(state, decrementAction);
console.log(state); // Logs: { count: 2 }

Let’s explain the code sample above:

  • Line 4: We pass in the current state and an action.

  • Lines 5–7: If the action has a type property of Increment, we increment the count property on state.

  • Lines 8–10: If the action has a type property of Decrement, we decrement the count property on state.

  • Line 11: If neither of the above is true, we do nothing and return the original state.

The TypeScript version of the example above is as follows:

In the code above:

  • Line 4: We add the any type annotations to the state and action parameters of the counterReducer to allow any type of these parameters.

Using primitive value as Redux action

Redux requires an action to be an object with a type property, as shown in the example above. React isn’t as strict. An action can be anything—even a primitive value like a number. For example, this is a valid reducer when using useReducer:

The above code at line 4 is a reducer function counterReducer that takes two parameters, state and value with the default values of 0 and 1. It returns the sum of state and value.

In fact, if you’ve used useState in React before, you’ve really used useReducer. The useState is simply an abstraction of useReducer. For our purposes, we’ll stick to a model closer to Redux, where actions are objects with a type property, since that pattern will work almost universally.

The useReducer hook of Redux and React adds some extra functionality around emitting changes and telling React to update the state of a component accordingly—as opposed to repeatedly setting a variable, as shown above—but the basic principles are the same regardless of what library we’re using.