{"id":297101,"date":"2019-10-24T07:21:52","date_gmt":"2019-10-24T14:21:52","guid":{"rendered":"https:\/\/css-tricks.com\/?p=297101"},"modified":"2019-10-24T07:30:18","modified_gmt":"2019-10-24T14:30:18","slug":"understanding-how-reducers-are-used-in-redux","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/understanding-how-reducers-are-used-in-redux\/","title":{"rendered":"Understanding How Reducers are Used in Redux"},"content":{"rendered":"

A reducer is a function<\/strong> that determines changes<\/strong> to an application\u2019s state.<\/strong> It uses the action<\/strong> it receives to determine this change. We have tools, like Redux<\/a>, that help manage an application\u2019s state changes in a single store so that they behave consistently.<\/p>\n

Why do we mention Redux when talking about reducers? Redux relies heavily on reducer functions that take the previous state and an action in order to execute the next state.<\/p>\n

We\u2019re going to focus squarely on reducers is in this post. Our goal is to get comfortable working with the reducer function so that we can see how it is used to update the state of an application \u2014 and ultimately understand the role they play in a state manager, like Redux.<\/p>\n

<\/p>\n

What we mean by \u201cstate\u201d<\/h3>\n

State changes are based on a user\u2019s interaction, or even something like a network request. If the application\u2019s state is managed by Redux, the changes happen inside a reducer function \u2014 this is the only place where state changes happen. The reducer function makes use of the initial state<\/strong> of the application and something called action<\/strong>, to determine what the new state<\/strong> will look like.<\/p>\n

If we were in math class, we could say:<\/p>\n

initial state + action = new state<\/code><\/pre>\n

In terms of an actual reducer function, that looks like this:<\/p>\n

const contactReducer = (state = initialState, action) => {\r\n  \/\/ Do something\r\n}<\/code><\/pre>\n

Where do we get that initial state and action? Those are things we define.<\/p>\n

The state parameter<\/h3>\n

The state<\/code> parameter that gets passed to the reducer function has to be the current state of the application. In this case, we\u2019re calling that our initialState<\/code> because it will be the first (and current) state and nothing will precede it.<\/p>\n

contactReducer(initialState, action)<\/code><\/pre>\n

Let\u2019s say the initial state of our app is an empty list of contacts and our action is adding a new contact to the list.<\/p>\n

const initialState = {\r\n  contacts: []\r\n}<\/code><\/pre>\n

That creates our initialState<\/code>, which is equal to the state<\/code> parameter we need for the reducer function.<\/p>\n

The action parameter<\/h3>\n

An action<\/code> is an object that contains two keys and their values. The state update that happens in the reducer is always dependent on the value of action.type<\/code>. In this scenario, we are demonstrating what happens when the user tries to create a new contact. So, let\u2019s define the action.type<\/code> as NEW_CONTACT<\/code>.<\/p>\n

const action = {\r\n  type: 'NEW_CONTACT',\r\n  name: 'John Doe',\r\n  location: 'Lagos Nigeria',\r\n  email: 'johndoe@example.com'\r\n}<\/code><\/pre>\n

There is typically a payload<\/code> value that contains what the user is sending and would be used to update the state of the application. It is important to note that action.type<\/code> is required, but action.payload<\/code> is optional. Making use of payload<\/code> brings a level of structure to how the action object looks like.<\/p>\n

Updating state<\/h3>\n

The state is meant to be immutable<\/code>, meaning it shouldn\u2019t be changed directly. To create an updated state, we can make use of Object.assign<\/a><\/code> or opt for the spread operator<\/a>.<\/p>\n

Object.assign<\/h4>\n
const contactReducer = (state, action) => {\r\n  switch (action.type) {\r\n    case 'NEW_CONTACT':\r\n    return Object.assign({}, state, {\r\n      contacts: [\r\n        ...state.contacts,\r\n        action.payload\r\n      ]\r\n    })\r\n    default:\r\n      return state\r\n  }\r\n}<\/code><\/pre>\n

In the above example, we made use of the Object.assign()<\/code> to make sure that we do not change the state value directly. Instead, it allows us to return a new object which is filled with the state that is passed to it and the payload sent by the user.<\/p>\n

To make use of Object.assign()<\/code>, it is important that the first argument is an empty object. Passing the state as the first argument will cause it to be mutated, which is what we\u2019re trying to avoid in order to keep things consistent.<\/p>\n

The spread operator<\/h4>\n

The alternative to object.assign()<\/code> is to make use of the spread operator, like so:<\/p>\n

const contactReducer = (state, action) => {\r\n  switch (action.type) {\r\n    case 'NEW_CONTACT':\r\n    return {\r\n        ...state, contacts:\r\n        [...state.contacts, action.payload]\r\n    }\r\n    default:\r\n      return state\r\n  }\r\n}<\/code><\/pre>\n

This ensures that the incoming state stays intact as we append the new item to the bottom.<\/p>\n

Working with a switch statement<\/h3>\n

Earlier, we noted that the update that happens depends on the value of action.type<\/code>. The switch statement conditionally determines the kind of update we’re dealing with, based on the value of the action.type<\/code>.<\/p>\n

That means that a typical reducer will look like this:<\/p>\n

const addContact = (state, action) => {\r\n  switch (action.type) {\r\n    case 'NEW_CONTACT':\r\n    return {\r\n        ...state, contacts:\r\n        [...state.contacts, action.payload]\r\n    }\r\n    case 'UPDATE_CONTACT':\r\n      return {\r\n        \/\/ Handle contact update\r\n      }\r\n    case 'DELETE_CONTACT':\r\n      return {\r\n        \/\/ Handle contact delete\r\n      }\r\n    case 'EMPTY_CONTACT_LIST':\r\n      return {\r\n        \/\/ Handle contact list\r\n      }\r\n    default:\r\n      return state\r\n  }\r\n}<\/code><\/pre>\n

It\u2019s important that we return state our default<\/code> for when the value of action.type<\/code> specified in the action object does not match what we have in the reducer \u2014 say, if for some unknown reason, the action looks like this:<\/p>\n

const action = {\r\n  type: 'UPDATE_USER_AGE',\r\n  payload: {\r\n    age: 19\r\n  }\r\n}<\/code><\/pre>\n

Since we don\u2019t have this kind of action type, we\u2019ll want to return what we have in the state (the current state of the application) instead. All that means is we\u2019re unsure of what the user is trying to achieve at the moment.<\/p>\n

Putting everything together<\/h3>\n

Here\u2019s a simple example of how I implemented the reducer function in React.<\/p>\n

\n See the Pen
\n reducer example<\/a> by Kingsley Silas Chijioke (
@kinsomicrote<\/a>)
\n on
CodePen<\/a>.<\/span>\n<\/p>\n

You can see that I didn\u2019t make use of Redux, but this is very much the same way Redux uses reducers to store and update state changes. The primary state update happens in the reducer function, and the value it returns sets the updated state of the application.<\/p>\n

Want to give it a try? You can extend the reducer function to allow the user to update the age of a contact. I\u2019d like to see what you come up with in the comment section!<\/p>\n

Understanding the role that reducers play in Redux should give you a better understanding of what happens underneath the hood. If you are interested in reading more about using reducers in Redux, it\u2019s worth checking out the official documentation<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"

A reducer is a function that determines changes to an application\u2019s state. It uses the action it receives to determine this change. We have tools, like Redux, that help manage an application\u2019s state changes in a single store so that they behave consistently. Why do we mention Redux when talking about reducers? Redux relies heavily […]<\/p>\n","protected":false},"author":251966,"featured_media":297827,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[557,1444,656,1093],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/10\/redux-logo.png?fit=1200%2C600&ssl=1","jetpack-related-posts":[],"featured_media_src_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/10\/redux-logo.png?fit=1024%2C512&ssl=1","_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/297101"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/251966"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=297101"}],"version-history":[{"count":4,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/297101\/revisions"}],"predecessor-version":[{"id":297105,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/297101\/revisions\/297105"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/297827"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=297101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=297101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=297101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}