0

I have an app that has a list that when an item is clicked, populates another list with data that is in a sub-category of the selected list item. When a list item is clicked in the parent list, an API call goes and retrieves data to populate the child list. Multiple items result in multiple API calls.

When multiple items in the parent list are clicked, I need to add multiple children from each respective parent to the child list. I am trying to limit the number of dependencies in my app and therefore I am using as much ES6+ as possible.

I am using the spread operator to make multiple shallow copies of my nested state. The state slice I am struggling with looks like this:

{
  tables: {
    tablesLoading: false,
    error: null,
    selectedTables: [],
    tables: {
      byId: {
        '9311fe20-dea9-11e9-ba2f-4fe2a4bdbda0': {
          id: '9311fe20-dea9-11e9-ba2f-4fe2a4bdbda0',
          value: 'Sample_1a',
          fields: []
        },
        '9311fe21-dea9-11e9-ba2f-4fe2a4bdbda0': {
          id: '9311fe21-dea9-11e9-ba2f-4fe2a4bdbda0',
          value: 'Sample_1b',
          fields: []
        },
        '93ea35b0-dea9-11e9-ba2f-4fe2a4bdbda0': {
          id: '93ea35b0-dea9-11e9-ba2f-4fe2a4bdbda0',
          value: 'Sample_2a',
          fields: []
        }
      },
      allIds: [
        '9311fe20-dea9-11e9-ba2f-4fe2a4bdbda0',
        '9311fe21-dea9-11e9-ba2f-4fe2a4bdbda0',
        '93ea35b0-dea9-11e9-ba2f-4fe2a4bdbda0'
      ]
    }
  }
}

The initial API call pulls the data corresponding to the first two ID's ( '9311fe20-dea9-11e9-ba2f-4fe2a4bdbda0' and '9311fe21-dea9-11e9-ba2f-4fe2a4bdbda0') from a server. I then click another item in the parent list and want to add the third item to the tables.byId object and then add the corresponding ID to the tables.allIds array. My code for that is:

const tableRequestSuccess = (state, action) => {
    const tableVals = action.tableVals;
    const datasetName = action.datasetName;  
    const tableUUIDs = tableVals[datasetName].map(val=>(uuidv1())); 
    let addedtablesById = {};
    for (let i = 0; i<tableUUIDs.length; i++){ 
        let tableId = tableUUIDs[i];
        addedtablesById[tableId]={
            id: tableId,
            value: tableVals[datasetName][i],
            fields: []
        }
    }
    **const updatedTablesById =  updateObject(state.tables.byId, addedtablesById)**
    const updatetableAllIds = [...state.tables.allIds, ...tableUUIDs]

    const updatedProperties = {
        byId: updatedTablesById,
        allIds: updatetableAllIds
    };
    return updateObject(state, {
        tablesLoading: false,
        error: null,
        tables: updateObject(state.tables, updatedProperties)
    });
}

My problem is that I am not sure how to do a copy on the part of my state tree where the individual objects are stored, i.e. state.tables.byId.THE_RESPECTIVE_IDS. This leaves me with the inner most objects having a reference to the original objects and therefore the state won't be updated immutably. But because the ID's will vary and the number will constantly change, I am not sure how to copy those last objects. I suspect all the state up to that point has been cloned over.

I have created a helper function for readability:

export const updateObject = (oldObject, updatedProperties) => {
    return {
        ...oldObject,
        ...updatedProperties
    }
}

Any pointers on how to get this done using the spread operator?

  • Deep Copy: https://stackoverflow.com/questions/20662319/javascript-deep-copy-using-json – Oleg Sep 24 '19 at 09:56
  • 1
    Possible duplicate of [Deep copy in ES6 using the spread syntax](https://stackoverflow.com/questions/38416020/deep-copy-in-es6-using-the-spread-syntax) – ponury-kostek Sep 24 '19 at 09:57
  • I have read both these linked answers. I wanted to avoid using an external package, as mentioned in the question, and wanted to try and use the spread operator for multiple nested shallow copies rather than a deep clone. I am assuming that this is not best practice then? –  Sep 24 '19 at 10:05

0 Answers0