Search code examples
arraysvue.jskey

Accessing JavaScript array of objects by object key, reactively


let arr = [{id:'one',val:1},{id:'two',val:2}]
for( let ii of arr ) {
    if( ii.hasOwnProperty('id') ) arr[ii.id] = ii
}

The above code allows us to access the array by the id key, e.g. arr['one'] //{id:'one', val:1}.

But the code needs to re-run after mutating the array by adding or deleting items. Is there a way of making the mutation automatic/reactive using JavaScript or Vue?


Solution

  • A pure js solution using the Proxy API, I think it's what you want.

    But why do you use id as a key to add the original array? It is not iterable when using for to loop the array. That's weird and pointless, in my opinion.

    const reactiveCallback = (arr) => {
      for(const item of arr) {
        if(item.hasOwnProperty('id')) {
          arr[item.id] = item
        }
      }
      console.log(`new arr =`, arr)
    }
    
    const arr = [{id:'one', val:1}, {id:'two', val:2}]
    
    const proxy = new Proxy(arr, {
      get: function (target, prop, receiver) {
        // delay
        setTimeout(() => {
          reactiveCallback(arr)
        }, 0);
        return target[prop];
      },
    });
    
    proxy.push({id:'three', val: 3})
    proxy.pop()

    more meaningful solution

    If you want to use id as a key of an object instead of the index of an array.

    const arr = [{id:'one', val:1}, {id:'two', val:2}]
    let arrObj = {}
    const reactiveCallback = (arr) => {
      arrObj = arr.reduce((obj, item) => {
        obj[item.id] = item;
        return obj;
      }, {})
      console.log(`new arr copy object =`, arrObj)
    }
    
    const proxy = new Proxy(arr, {
      get: function (target, prop, receiver) {
        // delay
        setTimeout(() => {
          reactiveCallback(arr)
        }, 0);
        return target[prop];
      },
    });
    
    proxy.push({id:'three', val: 3})
    proxy.pop()