eozzy
eozzy

Reputation: 68710

Reduce to object path

I need a function to set value on a nested object property. The object path is an array, which I can't seem to figure out how to reduce so it maps to the object correctly.

This is what I have:

var store = {
    config: {
        default: {
            value: 'foo' 
        }
    }
};

function setValue({ object, objectPath, value } = {}) {
        properties = objectPath.reduce((acc, prop) => {
            acc[prop];
            return store[acc];
        });
};

setValue({ 
    object: 'config', 
    objectPath: [ 'default', 'value' ],
    value: 'bar'
});

Upvotes: 3

Views: 736

Answers (1)

Phil
Phil

Reputation: 164910

In order to actually set a value, you'll want to navigate using all but the last path element, saving the last one for the actual value assignment.

In your reducer, you should initialise the accumulator to the top-level object and return each matching object as you go so the final return value is the inner-most object.

For example

var store = {
    config: {
        default: {
            value: 'foo' 
        }
    }
};

function setValue({ object, objectPath, value } = {}) {
  // create a navigation path using the initial store key "object" and
  // the objectPath minus the last element
  let navigate = [object, ...objectPath.slice(0, -1)]
  
  // reduce to find / create the store[nav0][nav1][nav2]... element
  let valueObj = navigate.reduce((obj, prop) => {
    // create an empty object if required
    if (typeof obj[prop] !== 'object') {
      obj[prop] = Object.create(null)
    }
    return obj[prop]
  }, store)
  
  // set the value
  valueObj[objectPath[objectPath.length - 1]] = value
};

setValue({ 
    object: 'config', 
    objectPath: [ 'default', 'value' ],
    value: 'bar'
});

console.info(store)

Upvotes: 2

Related Questions