首页 > 解决方案 > Iterate through nested objects

问题描述

I am creating a React app and have the following list:

const list = [
    {
        id: '1',
        task: 'task 1',
        activities: [{
            'Google': [
                {url: 'https://www.google.com'},
                {visited: false}
            ],
            'Yahoo': [
                {url: 'https://www.yahoo.com'},
                {visited: false}
            ],
            'Bing': [
                {url: 'https://www.bing.com'},
                {visited: false}
            ]
        }],
        visitedAll: false
    },
    {
        id: '2',
        task: 'task 2',
        activities: [{
            'Facebook': [
                {url: 'https://www.facebook.com'},
                {visited: false}
            ],
            'Instagram': [
                {url: 'https://www.instagram.com'},
                {visited: false}
            ],
            'Twitter': [
                {url: 'https://www.twitter.com'},
                {visited: false}
            ]
        }],
        visitedAll: false
    }
];

I am iterating through the list like so:

<ul>
    {list.map(item => (
        <li key={item.id}>
           {item.task}
           <ul>
               {Object.keys(item.activities[0]).map((act, i) => <li key={i}>{act}</li>)}
           </ul>
        </li>
    ))}
</ul>

Which will produce the following output:

  1. How can I wrap the submenu list items with their corresponding anchors?
  2. How do I add an onClick event which will set the visited key to true for each item?

标签: javascriptarraysreactjsobject

解决方案


您可以首先activities使用方法将属性修改为一个对象reduce,然后您可以为子项创建单独的组件,其中每个子项都具有visited属性的状态。

const {useState} = React;

const list = [{"id":"1","task":"task 1","activities":[{"Google":[{"url":"https://www.google.com"},{"visited":false}],"Yahoo":[{"url":"https://www.yahoo.com"},{"visited":false}],"Bing":[{"url":"https://www.bing.com"},{"visited":false}]}],"visitedAll":false},{"id":"2","task":"task 2","activities":[{"Facebook":[{"url":"https://www.facebook.com"},{"visited":false}],"Instagram":[{"url":"https://www.instagram.com"},{"visited":false}],"Twitter":[{"url":"https://www.twitter.com"},{"visited":false}]}],"visitedAll":false}]
.map(({activities, ...rest}) => ({
  ...rest, activities: activities.reduce((r, e) => Object.assign(r, e), {})
}))

const SubListItem = props => {
  const {data, name} = props;
  const [visited, setVisited] = useState(data[1].visited);
  
  const toggle = event => {
    event.preventDefault();
    setVisited(!visited);
  }
  
  return <li>
    <a style={{color: visited ? "green" : ''}}
    onClick={toggle} 
    href={data[0].url}>{name}</a>
  </li>
}

const List = ({data}) => <ul>
  {data.map(item => <li key={item.id}>
    <a href="">{item.task}</a>
    <ul>{Object.keys(item.activities).map(act => (
      <SubListItem key={act} name={act} data={item.activities[act]} />
    ))}</ul>
  </li>)}
</ul>

ReactDOM.render(<List data={list} />, document.querySelector("#app"))
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="app"></div>


推荐阅读