React - 如何映射嵌套对象值?

Posted

技术标签:

【中文标题】React - 如何映射嵌套对象值?【英文标题】:React - how to map nested object values? 【发布时间】:2017-09-11 10:20:47 【问题描述】:

我只是想在状态对象内映射嵌套值。数据结构如下:

我想映射每个里程碑名称,然后映射该里程碑内的所有任务。现在我正在尝试使用嵌套的地图函数来做到这一点,但我不确定我是否可以做到这一点。

渲染方法如下所示:

render() 
    return(
      <div>
        Object.keys(this.state.dataGoal).map( key => 
            return <div key=key>>

                     <header className="header">
                       <h1>this.state.dataGoal[key].name</h1>
                     </header>
                     <Wave />

                     <main className="content">
                       <p>this.state.dataGoal[key].description</p>

                         Object.keys(this.state.dataGoal[key].milestones).map( (milestone, innerIndex) => 
                             return <div key=milestone>
                                      milestone
                                      <p>Index: innerIndex</p>
                                    </div>
                         )
                     </main>

                   </div>
        )
      </div>
    );
  

我认为我可以通过将内部索引传递给这行代码以某种方式实现该结果:Object.keys(this.state.dataGoal[key].milestones),所以它看起来像:Object.keys(this.state.dataGoal[key].milestones[innerIndex])

但我不确定如何传递innerIndex。我也尝试通过milestone.name 获取里程碑名称,但这也不起作用。我想那是因为我必须指定密钥。

有人有想法吗?或者我应该以完全不同的方式映射整个对象?

很高兴得到任何帮助, 雅库布

【问题讨论】:

【参考方案1】:

您可以使用嵌套映射来映射里程碑,然后是任务数组:

 render() 
  return (
    <div>
      Object.keys(this.state.dataGoal.milestones).map((milestone) => 
        return (
          <div>
            this.state.dataGoal.milestones[milestone].tasks.map((task, idx) => 
              return (
              //whatever you wish to do with the task item
              )
            )
          </div>
        )
     )
    </div>
  )

【讨论】:

@Jakub Kašpar 这对你有用吗?因为除了有错误的闭括号之外,这个例子对我不起作用:| @mcmwhfy 我认为您在这里面临的问题是因为返回嵌套数据而不包含在 div 中,但是如果您使用最新版本的反应,您可以简单地返回一个数组,即映射的结果。无论如何,我更新了我的答案以处理包装 div 你说的有道理,但我不明白为什么在我的例子中对象看起来像这样的地方不起作用:[ id: 1, name: "Leanne Graham", username: "Bret", email: "Sincere@april.biz", address: street: "Kulas Light", suite: "Apt. 556", city: "Gwenborough", zipcode: "92998-3874", geo: lat: "-37.3159", lng: "81.1496" ]【参考方案2】:

你想要的是flatMapflatMap 接受一个数组和一个函数,该函数将应用于数组中的每个元素,您可以使用它们(例如)访问数组中每个对象内的属性。然后它返回一个新数组,其中包含来自其 lambda 的返回值:

function flatMap(arr, lambda) 
  return Array.prototype.concat.apply([], arr.map(lambda))

在我们的例子中,我们没有数组,我们有一个对象,所以我们不能直接使用flatMap。我们可以使用Object.values 将对象转换为其属性值的数组,然后创建一个使用传递的键访问对象的函数:

function tasksFromDataGoal(key) 
  return flatMap(Object.values(dataGoal[key].milestones), milestone => milestone.tasks)

工作示例:

function flatMap(arr, lambda) 
  return Array.prototype.concat.apply([], arr.map(lambda))


function tasksFromDataGoal(key) 
  return flatMap(Object.values(dataGoal[key].milestones), milestone => milestone.tasks)


const dataGoal =  123:  milestones:  milestone1:  tasks: ['a', 'b'] , milestone2:  tasks: ['c', 'd']    

alert(tasksFromDataGoal('123'))

flatMap这个实现的作者:https://gist.github.com/samgiles/762ee337dff48623e729

【讨论】:

@FaustoNA 感谢您的回复。我从来没有听说过这样的功能,所以再次感谢。我只是想实现这个解决方案,但我做错了。我将dataGoaltasks 常量放在第一个Object.keys(this.state.dataGoal).map 中,以获取键值,如下所示:const newDataGoal = this.state.dataGoal[key].milestones;const tasks = this.flatMap(Object.values(newDataGoal.milestones), milestone =&gt; milestone.tasks)。但我得到了Uncaught TypeError: Cannot convert undefined or null to object。我做错了吗?再次感谢您的帮助。 :) 没关系,错误可能如下: 1. 您使用的是this.flatMap。您应该将flatMap 放在其他地方并在没有this 的情况下使用它,flatMap 是一个实用函数,与您的组件没有直接关系。 2. 如果您的应用程序执行网络请求,您可能会将undefined 传递给Object.keys。试试if (this.state.dataGoal) 然后应用你的逻辑。【参考方案3】:

设法重构了渲染方法:

  render() 
    return(
      <div>
        Object.keys(this.state.dataGoal).map( (key, index) => 
          const newDataGoal = this.state.dataGoal[key].milestones;

          return <div key=key>

                   <header className="header">
                     <h1>this.state.dataGoal[key].name</h1>
                   </header>
                   <Wave />

                   <main className="content">
                     <p>this.state.dataGoal[key].description</p><br /><br />

                       Object.keys(this.state.dataGoal[key].milestones).map( (milestoneKey) => 
                         const milestonesData = this.state.dataGoal[key].milestones[milestoneKey];

                         return <div className="milestone-wrap" key=milestoneKey>
                                  <label className="milestone-label">milestonesData.name</label>

                                    Object.keys(milestonesData.tasks).map( (taskKey) => 
                                      return <div className="task clearfix" key=taskKey>
                                                  <input
                                                    className="checkbox-rounded"
                                                    name="task"
                                                    type="checkbox"
                                                    checked=milestonesData.tasks[taskKey].done
                                                    onChange=(e) => this.handleInputChange(e, key, taskKey) />
                                                  <div className="task-content">
                                                    <p className="task-name">milestonesData.tasks[taskKey].name</p>
                                                    <p className="task-date">milestonesData.tasks[taskKey].finishDate</p>
                                                  </div>
                                             </div>

                                    )

                                </div>

                       )
                   </main>

                 </div>
          )
      </div>
    );
  

【讨论】:

以上是关于React - 如何映射嵌套对象值?的主要内容,如果未能解决你的问题,请参考以下文章

反应:映射嵌套的对象数组

如何设置映射输入的嵌套 JSON 数组对象的状态

React - 通过对象数组映射以在 Material UI 中编辑日期文本字段

React 如何在嵌套数据对象中渲染动态图像

尝试在 React 中映射子对象时出现未定义错误

RestKit 0.20 嵌套对象映射(对象树的路径不同)