Rangle.io: React Training
gitbook
gitbook
  • Introduction
  • Setup
  • Functional JavaScript
  • ES6 constructs
    • Default Params
    • Template Literals
    • Destructuring
    • Arrow Functions
    • Promises
    • let and const
    • Modules
  • Thinking in Components
    • Atomic Design
    • Atomic Component Principles
    • Benefits of This Approach
    • The Process
    • Task #1
  • React Components
    • Stateless Components
    • Stateful Components
    • Stateful vs Stateless Components
    • Composition
    • Task #2
    • Task #3
    • Task #4
    • Task #5
  • Immutable
    • What Is Immutability?
    • The Case for Immutability
    • JavaScript Solutions
      • Object.assign
      • Object.freeze
    • Immutable.js Basics
      • Immutable.Map
        • Map.merge
      • Nested Objects
        • Deleting Keys
        • Maps are Iterable
      • Immutable.List
      • Performance
      • Persistent and Transient Data Structures
      • Official Documentation
    • Exercises
      • Task #1
      • Task #2
      • Task #3
      • Task #4
      • Task #5
      • Task #6
      • Task #7
  • Redux
    • Review of Reducers and Pure Functions
    • Redux Reducers
    • Redux Actions
    • Configuring your Application to use Redux
    • Using Redux with Components
    • Redux and Component Architecture
  • Routing
    • React Router
    • Router Redux
  • Forms
    • Redux Form
  • Testing
    • Setup
    • Components
    • Reducers
    • Actions
Powered by GitBook
On this page

Was this helpful?

  1. Redux

Redux Reducers

While a very simple idea, it is very powerful. With Redux, you replay a series of events into the reducer - and get your new application state as a result.

Reducers in a Redux application should not mutate the state, but return a copy of it, and be side-effect free. Lets take a look at a simple counter reducer.

Simple Reducer

const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
const DECREMENT_COUNTER = 'DECREMENT_COUNTER';

export default function counter(state = 0, action) {

  switch (action.type) {
    case INCREMENT_COUNTER:
      return state + 1;
    case DECREMENT_COUNTER:
      return state - 1;
    default:
      return state;
  }
}

We can see here that we are passing in an initial state, and an action. To handle each action - we have setup a switch statement. Instead of each reducer needing to explicitly subscribe to the dispatcher - every action gets passed into every reducer, which handles the action it is interested in or otherwise returns the state along to the next reducer.

Reducers in Redux should be side-effect free, that means that they should not modify things outside of the application state. Instead, they should reflect the state of the application. This is why side-effect causing operations, such as updating a record in a database, generating an id, etc should be handled elsewhere in the application - such as in the action creators, or middleware.

Another consideration when creating your reducers, is to ensure that they are immutable and not modifying the state of your application. If you mutate your application state, it can cause unexpected behavior. There are a few ways to help maintain immutability in your reducers. One, is using new ES6 features such as the spread operator for objects and arrays.

let immutableObjectReducer = (state = { someValue: 'value'} , action) => {
  switch(action.payload) {
    case SOME_ACTION:
    return Object.assign({}, state, { someValue: action.payload.value });
    default:
    return state;

  }
}

let immutableArrayReducer = (state = [1,2,3], action) => {
  switch(action.payload) {
    case ADD_ITEM:
      return [...state,action.payload.value]
    break;
    default:
    return state;
  }
}

However, if dealing with complex or deeply nested objects - it can be difficult to maintain immutability in your application using this syntax. This is where a library like ImmutableJS can help.

PreviousReview of Reducers and Pure FunctionsNextRedux Actions

Last updated 6 years ago

Was this helpful?