Redux in Russian
  • Read Me
  • Introduction
    • Motivation
    • Core Concepts
    • Three Principles
    • Prior Art
    • Learning Resources
    • Ecosystem
    • Examples
  • Basics
    • Actions
    • Reducers
    • Store
    • Data Flow
    • Usage with React
    • Example: Todo List
  • Advanced
    • Async Actions
    • Async Flow
    • Middleware
    • Usage with React Router
    • Example: Reddit API
    • Next Steps
  • Recipes
    • Configuring Your Store
    • Migrating to Redux
    • Using Object Spread Operator
    • Reducing Boilerplate
    • Server Rendering
    • Writing Tests
    • Computing Derived Data
    • Implementing Undo History
    • Isolating Subapps
    • Structuring Reducers
      • Prerequisite Concepts
      • Basic Reducer Structure
      • Splitting Reducer Logic
      • Refactoring Reducers Example
      • Using combineReducers
      • Beyond combineReducers
      • Normalizing State Shape
      • Updating Normalized Data
      • Reusing Reducer Logic
      • Immutable Update Patterns
      • Initializing State
    • Using Immutable.JS with Redux
  • FAQ
    • General
    • Reducers
    • Organizing State
    • Store Setup
    • Actions
    • Immutable Data
    • Code Structure
    • Performance
    • Design Decisions
    • React Redux
    • Miscellaneous
  • Troubleshooting
  • Glossary
  • API Reference
    • createStore
    • Store
    • combineReducers
    • applyMiddleware
    • bindActionCreators
    • compose
  • Change Log
  • Patrons
  • Feedback
Powered by GitBook
On this page
  1. Recipes

Using Object Spread Operator

PreviousMigrating to ReduxNextReducing Boilerplate

Last updated 6 years ago

Since one of the core tenets of Redux is to never mutate state, you'll often find yourself using to create copies of objects with new or updated values. For example, in the todoApp below Object.assign() is used to return a new state object with an updated visibilityFilter property:

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}

While effective, using Object.assign() can quickly make simple reducers difficult to read given its rather verbose syntax.

An alternative approach is to use the recent added to the JavaScript specification. It lets you use the spread (...) operator to copy enumerable properties from one object to another in a more succinct way. The object spread operator is conceptually similar to the ES6 . We can simplify the todoApp example above by using the object spread syntax:

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return { ...state, visibilityFilter: action.filter }
    default:
      return state
  }
}

The advantage of using the object spread syntax becomes more apparent when you're composing complex objects. Below getAddedIds maps an array of id values to an array of objects with values returned from getProduct and getQuantity.

return getAddedIds(state.cart).map(id =>
  Object.assign({}, getProduct(state.products, id), {
    quantity: getQuantity(state.cart, id)
  })
)

Object spread lets us simplify the above map call to:

return getAddedIds(state.cart).map(id => ({
  ...getProduct(state.products, id),
  quantity: getQuantity(state.cart, id)
}))
{
  "presets": ["@babel/preset-env"],
  "plugins": ["transform-object-rest-spread"]
}

While the object spread syntax is a proposal for ECMAScript and accepted for the 2018 specification release, you will still need to use a transpiler such as to use it in production systems. You should use the preset, install and add it individually to the plugins array in your .babelrc.

Object.assign()
object spread syntax
array spread operator
Stage 4
Babel
env
babel-plugin-transform-object-rest-spread