1

I'm trying some app in react redux and i have a problem with updating (push, remove, update) the nested array in state.

I have some object called service like this:

{
    name: 'xzy',
    properties: [
       { id: 1, sName: 'xxx'},
       { id: 2, sName: 'zzz'}, 
    ]
}

Whatever I did (in case of adding property to collection) in the reducer with the properties collection generate problem that all properties got same values as the last I had recently added -> Added property object is in service properties collection but the action replace all values in all properties in this collection. My reducer:

export function service(state = {}, action) {
        switch (action.type) {
            case 'ADD_NEW_PROPERTY':
                console.log(action.property) // correct new property
                const service = {
                    ...state, properties: [
                        ...state.properties, action.property
                    ]
                }
                console.log(service); // new property is pushed in collection but all properties get same values
                return service

            default:
                return state;
        }
    }

I have tried some solution with immutability-helper library and it generate the same problem:

export function service(state = {}, action) {
    case 'ADD_NEW_PROPERTY':

                return update(state, {properties: {$push: [action.property]}})

            default:
                return state;
        }

For example when I add new property { id: 1, sName: 'NEW'} to example above I will get this state:

{
    name: 'xzy',
    properties: [
       { id: 1, sName: 'NEW'},
       { id: 1, sName: 'NEW'}, 
       { id: 1, sName: 'NEW'}
    ]
}

Can someone help? :)

2
  • On the first look, the reducer looks right. Could you provide an exemple a component using it and his connection to Redux ? Commented Nov 23, 2017 at 15:44
  • connection to redux in my container is working. Somewhere I call this: dispatch(addNewProperty(property)) and the action: export function addNewProperty(property) { return { type: 'ADD_NEW_PROPERTY', property } } I think this working because the property data in reducer are good - when I do console.log(action.property) Commented Nov 23, 2017 at 15:58

4 Answers 4

2

Make a copy of action.property as well. Whatever is dispatching this action, it could be reusing the same object.

export function service(state = {}, action) {
  switch (action.type) {
    case 'ADD_NEW_PROPERTY':
      console.log(action.property) // correct new property
      const service = {
        ...state,
        properties: [
          ...state.properties, 
          { ...action.property }
        ]
      }
      console.log(service); // new property is pushed in collection but all properties get same values
      return service

    default:
      return state;
  }
}

Sign up to request clarification or add additional context in comments.

Comments

1

I'd recommend you to use Immutable data https://facebook.github.io/immutable-js/docs/#/List

import { fromJS, List } from 'immutable';

const initialState = fromJS({
  propeties: List([{ id: 1, sName: 'xyz' }]
}

function reducer(state = initialState, action) {
  case ADD_NEW_PROPERTY:
    return state
      .update('properties', list => list.push(action.property));
 // ...
}

1 Comment

Before considering a library, just learn what the language has to offer. You'll be impressed!
0

Your service reducer should probably look somewhat like this:

// Copy the state, because we're not allowed to overwrite the original argument
const service = { ...state }; 
service.properties.append(action.property)
return service

Comments

0

You should always copy the state before returning it.

  export default function(state = {}, action) {
  switch(action.type) {
    case 'GET_DATA_RECEIVE_COMPLETE': {
      const data  = action.firebaseData;
      const newState = Object.assign({}, state, {
        data
      });

      return newState
    }
    default:
      return state;

  }
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.