Search code examples
reactjsecmascript-6reduxecmascript-next

Using object rest to delete nested object


I have a react app with some redux state that looks like:

{
    shape1: {
        constraints: {
            constraint1: {
                key: value
            },
            constraint2: {
                key: value
            }
        }
    }, 
    shape2: {
        constraints: {
            constraint1: {
                key: value
            },
            constraint2: {
                key: value
            }
        }            
    }
}

I dispatch an action and want to delete one of the constraint objects, ie. constraint1 for shape1. Here is what my reducer looks like for this action, say I'm trying to delete constraint1 from shape1:

case DELETE_CONSTRAINT:
    shape = action.payload;    // ie. shape1, the parent of the constraint I 
                               // am trying to delete
    let {
        [shape]: {'constraints': 
            {'constraint1': deletedItem}
        }, ...newState  
    } = state;
    return newState;

This removes the entire shape1 object from the state instead of just the individual constraint1 object. Where I am going wrong/ what is the best approach for doing this? I'd prefer to use object rest in order to be consistent with the rest of my code.

Thanks.


Solution

  • When using the rest syntax in destructuring to get a slice of the object, you'll get everything else on the same "level".

    let {
        [shape]: {'constraints': 
            {'constraint1': deletedItem}
        }, ...newState  
    } = state;
    

    In this case newState takes everything else is everything but [shape].

    Since your state has multiple nesting levels, you'll have to extract the new constraints using destructuring and rest syntax, and then create a new state.

    const state = {
        shape1: {
            constraints: {
                constraint1: {
                    key: 'value'
                },
                constraint2: {
                    key: 'value'
                }
            }
        }, 
        shape2: {
            constraints: {
                constraint1: {
                    key: 'value'
                },
                constraint2: {
                    key: 'value'
                }
            }            
        }
    };
    
    const shape = 'shape1';
    const constraint = 'constraint1';
      
    // extract constraints
    const {
      [shape]: {
        constraints: {
          [constraint]: remove,
          ...constraints
        }  
      }
    } = state;
    
    // create the next state
    const newState = {
      ...state,
      [shape]: {
        ...state[shape], // if shape contains only constraints, you keep skip this
        constraints
      }
    }
    
    console.log(newState);