GuerillaRadio GuerillaRadio - 1 year ago 65
Javascript Question

ES6 - Looping through keys in object and then assigning to new object

On page load I am calling a metadata API which returns an object with the metadata type as the key name and an array of metadata objects as the value like so:

enter image description here

The metadata objects need to be simplified and altered to play nicely with my React input components (each object will be a separate checkbox or radio button with a value and label). I basically need to return the same format but with value and label keys instead of id, display_on, name etc. I am doing the following in my container component to alter the data ready for being passed via props to my form components. The issue is that

metadataFormattedForInput
always return an empty object.

function mapStateToProps(state, ownProps) {
const metadataFormattedForInput = {};
Object.keys(state.metadata).forEach((key) => {
const metadataOptions = [];
state.metadata[key].map(option => (
metadataOptions.push({ value: option.id, label: option.name })
));
return (
Object.assign({}, metadataFormattedForInput, {
[key]: metadataOptions,
})
);
});

return {
metadataOptions: metadataFormattedForInput,
};
}

Answer Source

The culprit is the way you're using Object.assign (you're adding the properties to an empty object that you just discard afterwards because it's returned in a forEach call). However, Object.assign is unnecessary:

function mapStateToProps(state, ownProps) {
  const metadataFormattedForInput = {};

  Object.keys(state.metadata).forEach(key => {
    metadataFormattedForInput[key] = state.metadata[key].map(option =>
      ({ value: option.id, label: option.name })
    );
  });

  return {
    metadataOptions: metadataFormattedForInput,
  };
}

const metadata = {
  phaseofthegame: [{id: 1, name: 'foo'}],
  theme: [{id: 2, name: 'bar'}]
};

console.log(
  mapStateToProps({ metadata }).metadataOptions
);

If you want to keep using Object.assign, then you can combine it with Array.reduce:

function mapStateToProps(state, ownProps) {
  const renameProps = (acc, key) => Object.assign(acc, {
    [key]: state.metadata[key].map(option =>
      ({ value: option.id, label: option.name })
    )
  });

  const metadataOptions =
    Object.keys(state.metadata).reduce(renameProps, {});

  return { metadataOptions };
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download