ES6 - 循环访问对象中的键,然后分配给新对象

时间:2017-08-16 09:52:57

标签: javascript ecmascript-6

在页面加载时,我正在调用一个元数据API,它返回一个对象,其中元数据类型作为键名,元数据对象数组作为值,如下所示:

enter image description here

需要简化和更改元数据对象,以便与我的React输入组件很好地配合(每个对象将是一个单独的复选框或带有值和标签的单选按钮)。我基本上需要返回相同的格式,但使用值和标签键而不是id,display_on,name等。我在容器组件中执行以下操作以更改准备好通过props传递给我的表单组件的数据。问题是metadataFormattedForInput总是返回一个空对象。

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,
  };
}

3 个答案:

答案 0 :(得分:3)

罪魁祸首就是你使用Object.assign的方式(你将属性添加到之后丢弃的空对象,因为它是在forEach调用中返回的)。但是,Object.assign是不必要的:

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
);

如果您想继续使用Object.assign,则可以将其与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 };
}

答案 1 :(得分:0)

以下是您的代码的一些问题:

  • 您以错误的方式使用forEachforEach不会返回任何值。如果您想要返回一些值,请使用map
  • 此外,您正在使用map并使用它forEach,即您没有使用返回值

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

答案 2 :(得分:0)

正如其他人所说,以及其他一些问题:

  • forEach回调中返回值无效
  • 另一方面,map回调 应该返回值
  • Object.assign不会改变第二个参数,因此metadataFormattedForInput根本不会被修改

这是一种实现此功能的方法,将Object.assign调用移到map之外,并使用扩展语法构建输出:

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


var state = {
    metadata: {
        phaseofthegame: [
            { id: 123, display_on: ['a', 'b'], name: 'Attacking' },
            { id: 456, display_on: ['c', 'd'], name: 'Transition to Attack' },
        ],
        theme: [
            { id: 789, display_on: ['e', 'f'], name: 'Rondo' },
            { id: 101, display_on: ['g', 'h'], name: 'Defending Individually' },
        ]
    }
};

state = mapStateToProps(state);

console.log(JSON.stringify(state, null, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }