0

I am still getting my head around functional programming and how to return a non mutated object from a reducer.

I am trying to replace the contents of an old object in a reducer, without mutating the old state.

so if the old state was

 {
        Actors:"Michael Keaton, Jack Nicholson, Kim Basinger, Robert Wuhl"
        Awards:"Won 1 Oscar. Another 9 wins & 22 nominations."
        Country:"USA, UK"
        Director:"Tim Burton"
 }

and the new state is

{
        Actors:"George Clooney"
        Awards:"Won 9 Oscars."
        Country:"USA"
        Director:"Quentin Tarantino"
 }

My reducer looks like this

function reducer(state = {}, action){
  switch(action.type) {
    case 'GET_MOVIE':
      return //new Array here that has not been mutatated
    default:
        return state;
  }
}

My payload looks like this

{
    Actors:"Michael Keaton, Jack Nicholson, Kim Basinger, Robert Wuhl"
    Awards:"Won 1 Oscar. Another 9 wins & 22 nominations."
    Country:"USA, UK"
    Director:"Tim Burton"
}
3
  • How is your action.payload looks like? Commented Jan 16, 2017 at 17:42
  • Your payload is the old state? Commented Jan 16, 2017 at 17:54
  • Where is the array here? Commented Jan 16, 2017 at 18:04

3 Answers 3

1

If all the values of your object are changing everytime, you can simply return that new payload as new state. But if only some of the values are changing then You can use ES6 Object.assign or object-assign as npm module.

If all the values are changing everytime then,

function reducer(state = {}, action){
   switch(action.type) {
    case 'GET_MOVIE':
      return action.payload;
    default:
        return state;
  }
}

If some of the values are changing then,

function reducer(state = {}, action){
   switch(action.type) {
    case 'GET_MOVIE':
      // let say Actors field changed, then 
      return Object.assign({}, state, {Actors: "Michael Keaton, Jack Nicholson, Kim Basinger, Robert Wuhl" });
    default:
        return state;
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I am a bit confused about why you need array operators when you're dealing with an object. With this current state, you can do this one of two ways, depending on your build tools, polyfills, and/or target browsers.

Using Object.assign()

function reducer(state = {}, action){
  switch(action.type) {
    case 'GET_MOVIE':
      return Object.assign({}, state, {
        Actors: action.Actors,
        Awards: action.Awards,
        Country: action.Country,
        Director: action.Director
      });
    default:
        return state;
  }
}

Or with spread operator ...

function reducer(state = {}, action){
  switch(action.type) {
    case 'GET_MOVIE':
      return {
        ...state,
        Actors: action.Actors,
        Awards: action.Awards,
        Country: action.Country,
        Director: action.Director
      }
    default:
        return state;
  }
}

1 Comment

What if you need only a part of the state object. Say actors is an object and you want to change only Actors.name. for example
0

Simply use non-mutative functions and return the new data structure.

If your state is simply {a: 1, b: 2, c: 3} and you want it to become {a: 4, b: 5, c: 6} just return {a: 4, b: 5, c: 6}.

function reducer(state = {a: 1, b: 2, c: 3}, action){
  switch(action.type) {
    case 'GET_MOVIE':
      return action.payload // assuming action.payload = {a: 4, b: 5, c: 6}
    default:
        return state;
  }
}

It gets more interesting when you want the new state = [{a:1,b:2,c:3},{a:4, b:5, c: 6}].

For a good list of mutative vs non-mutative functions, this is helpful: https://jeff.is/blog/mutative-vs-non-mutative-array-methods-in-js.html

I've also found React's immutability helpers nice for deeply nested structures. They use a Mongo style syntax.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.