【问题标题】:ES6 - Looping through keys in object and then assigning to new objectES6 - 遍历对象中的键,然后分配给新对象
【发布时间】:2017-08-16 19:30:26
【问题描述】:

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

需要简化和更改元数据对象以与我的 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,
  };
}

【问题讨论】:

  • 你能分享metadata对象吗..?
  • 返回forEach 循环真的没有任何作用?
  • 除了从 forEach 返回之外,为什么还要使用 state.metadata[key].map 并丢弃结果数组?使用const metadataOptions = state.metadata[key].map(option => ({ value: option.id, label: option.name });
  • metadataFormattedForInput 不会被Object.assign 的调用修改。事实上,Object.assign 是完全没用的,既不保留第一个参数,也不保留返回值。
  • 实际上只需要从 Object.assign 函数中删除空 {},但接受的答案是一种更好的编写方式。

标签: javascript ecmascript-6


【解决方案1】:

罪魁祸首是您使用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 };
}

【讨论】:

  • ES6 允许您在值相同的情况下简写对象文字中的属性名称,如果您选择 metadataOptions 而不是 metadataFormattedForInput 作为名称,您可以简写 {metadataOptions}{metadata}
【解决方案2】:

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

  • 您以错误的方式使用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,
      };
    }
    

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-08-09
      • 2018-04-12
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      相关资源
      最近更新 更多