简体   繁体   English

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

[英]React - how to map nested object values?

I am just trying to map nested values inside of a state object.我只是想在状态对象内映射嵌套值。 The data structure looks like so:数据结构如下所示:

在此处输入图片说明

I want to map each milestone name and then all tasks inside of that milestone.我想映射每个里程碑名称,然后映射该里程碑内的所有任务。 Right now I am trying to do so with nested map functions but I am not sure if I can do this.现在我正在尝试使用嵌套的地图函数来做到这一点,但我不确定我是否可以做到这一点。

The render method looks like so:渲染方法如下所示:

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

I think that I could somehow achieve that result by passing the inner index to this line of code: {Object.keys(this.state.dataGoal[key].milestones) so it would look like: {Object.keys(this.state.dataGoal[key].milestones[innerIndex]) .我认为我可以通过将内部索引传递给这行代码来以某种方式实现该结果: {Object.keys(this.state.dataGoal[key].milestones)所以它看起来像: {Object.keys(this.state.dataGoal[key].milestones[innerIndex])

But I am not sure how to pass the innerIndex up.但我不确定如何传递innerIndex I have also tried to get the milestone name by {milestone.name} but that doesn't work either.我还尝试通过{milestone.name}获取里程碑名称,但这也不起作用。 I guess that's because I have to specify the key.我想那是因为我必须指定密钥。

Does anybody have an idea?有人有想法吗? Or should I map the whole object in a totally different way?或者我应该以完全不同的方式映射整个对象?

Glad for any help, Jakub很高兴得到任何帮助,Jakub

You can use nested maps to map over the milestones and then the tasks array:您可以使用嵌套映射映射里程碑和任务数组:

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

What you want is flatMap .你想要的是flatMap flatMap takes an array and a function that will be applied to each element in the array, which you can use to (for example) access properties inside each object in the array. flatMap接受一个数组和一个将应用于数组中每个元素的函数,您可以使用它来(例如)访问数组中每个对象内的属性。 It then returns a new array with the returned values from its lambda :然后它返回一个新数组,其中包含来自其lambda的返回值:

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

In our case, we don't have an array, we have an object so we can't use flatMap directly.在我们的例子中,我们没有数组,我们有一个对象,所以我们不能直接使用flatMap We can convert the object to an array of its properties' values with Object.values and then make a function that accesses the object with the passed key:我们可以使用Object.values将对象转换为其属性值的数组,然后创建一个使用传递的键访问对象的函数:

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

Working example:工作示例:

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

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

Managed to refactor the render method:管理重构渲染方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM