2

I have a reduxreducer which looks like this:

const initialState = {
    visitedData:{specialty:false,review:false,reviewUpgrade:false}
}

const myred= (state = initialState, action) => {
    switch (action.type) {
        case 'GO_FOR_IT_SON':
            return Object.assign({}, state, { visitedData: action.data });

        default:
            return state
    }
}

Now from my reactcomponent I will call something like:

 store.dispatch({type: 'GO_FOR_IT_SON', data:{review:true} });

or:

 store.dispatch({type: 'GO_FOR_IT_SON', data:{specialty:false} });

So each of these statements are supposed to set one of the properties of visitedData to true/false and leaving the other ones intact. How can I set each of the properties of visitedData to true/false and leaving the other properties unchanged?

bier hier
  • 20,970
  • 42
  • 97
  • 166
  • What do you mean by How can I set each of the properties of visitedData to true/false and leaving the other properties unchanged? Do you want to change multiple properties at the same time? Or do you want to change visitedData properties without changing other state properties? – Vincent D'amour Mar 22 '17 at 04:26
  • check this: http://stackoverflow.com/questions/40096036/how-to-update-a-value-of-a-nested-object-in-a-reducer – Mayank Shukla Mar 22 '17 at 04:28

5 Answers5

0

I would recommend to have a reducer and action for every changable property:

import { combineReducers } from 'redux';

const specialty = (state = false, action) => {
  if (action.type === 'TOGGLE_SPECIALTY') {
    return action.data;
  }
  return state;
};

const review = (state = false, action) => {
  if (action.type === 'TOGGLE_REVIEW') {
    return action.data;
  }
  return state;
};

const myred = combineReducers({
  specialty,
  review
});

But in your situation, the solution would be:

const myred= (state = initialState, action) => {
  switch (action.type) {
    case 'GO_FOR_IT_SON':
      return Object.assign({}, state, {
        visitedData: Object.assign({}, state.visitedData, action.data)
      });

    default:
      return state
  }
}
Amberlamps
  • 39,180
  • 5
  • 43
  • 53
0

I think this will work:

return Object.assign({}, state, {
   visitedData: Object.assign({}, state.visitedData, action.data)
});

Check this example:

let a = {b: {a : 1, b : 2, c : 5} };
let b = {a : 5};

let k = Object.assign({}, a, {b: Object.assign({}, a.b, b)});

console.log(k);
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
0

Same as other solution. I suggest to separate object merging into another line and use object spread for more readable

const myred = (state = initialState, action) => {
  switch (action.type) {
    case 'GO_FOR_IT_SON':
      let newVisitedData = {
        ...state.visitedData,
        ...action.data
      }
      return { visitedData: newVisitedData }
    default:
      return state
  }
}
Jirat Ki
  • 140
  • 2
  • 5
0

const initialState = {
      visitedData: {
      specialty: false,
      review: false,
      reviewUpgrade: false
    }
}

const myred = (state = initialState, action) => {
    switch (action.type) {
        case 'GO_FOR_IT_SON':
            return {...state, visitedData: {...state.visitedData, action.data}}
        default:
            return state
    }
}

as you did with state - Object.assign, you should do the same with visitedData object or use spread operator instead object.assign

Gayane
  • 547
  • 4
  • 12
-1

A straight forward brute force ways:

Edit use lodash cloneDeep

const _ = require('lodash')

let newState = _.cloneDeep(state)

for(let key in action) {
    newState.visitedData[key] = action[key]
}
Rick Lee
  • 743
  • 2
  • 7
  • 19