2016-07-22 3 views
0

У меня есть json-файл с древовидной структурой, который может спуститься на несколько уровней, что выглядит примерно так, и я пытаюсь преобразовать его в меню (с дочерними элементами sub -menu):Reactjs: проблема с итерацией по вложенному массиву json

[ 
    { 
    "label": { 
     "en": "Home" 
    }, 
    "icon": "/images/nav/home.png", 
    "link": "/", 
    "type": "basic" 
    }, 
    { 
    "label": { 
     "en": "Channels" 
    }, 
    "icon": "/images/nav/channels.png", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "Getting Started" 
     }, 
     "link": "/getting-started", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Recommendations" 
     }, 
     "link": "/recommendations", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Calendar View" 
     }, 
     "link": "/calendar", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "My Pictures" 
     }, 
     "link": "/account/media", 
     "type": "basic" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "label": { 
      "en": "All Channels" 
     }, 
     "link": "/channels", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Channel 1" 
     }, 
     "link": "/channels/channel-1", 
     "type": "statuses", 
     "datasource": "/data/1", 
     "children": [ 
      { 
      "label": { 
       "en": "Channel 1-1" 
      }, 
      "link": "/channels/channel-1-1", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 1-2" 
      }, 
      "link": "/channels/channel-1-2", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 1-3" 
      }, 
      "link": "/channels/channel-1-3", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 1-4" 
      }, 
      "link": "/channels/channel-1-4", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 1-5" 
      }, 
      "link": "/channels/channel-1-5", 
      "type": "basic" 
      } 
     ] 
     }, 
     { 
     "label": { 
      "en": "Channel 2" 
     }, 
     "link": "/channels/2", 
     "type": "statuses", 
     "datasource": "/data/2", 
     "children": [ 
      { 
      "label": { 
       "en": "Channel 2" 
      }, 
      "link": "/channels/channel-2", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 2-1" 
      }, 
      "link": "/channels/channel-2-1", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 2-2" 
      }, 
      "link": "/channels/channel-2-2", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 2-3" 
      }, 
      "link": "/channels/channel-2-3", 
      "type": "basic" 
      }, 
      { 
      "label": { 
       "en": "Channel 2-4" 
      }, 
      "link": "/channels/channel-2-4", 
      "type": "basic" 
      } 
     ] 
     }, 
     { 
     "type": "custom", 
     "content": "<div><span class=\"green_bull\">&bull;</span>Currently Online</div><div><span class=\"red_bull\">&bull;</span>Currently Offline</div>" 
     } 
    ] 
    }, 
    { 
    "label": { 
     "en": "Shows" 
    }, 
    "icon": "/images/nav/shows.png", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "LIVE" 
     }, 
     "link": "/live", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Browse Shows" 
     }, 
     "link": "/live", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Full Schedule" 
     }, 
     "link": "/live", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Upcoming Shows" 
     }, 
     "type": "components", 
     "component": "navShow", 
     "datasource": "/shows/upcoming?limit=3" 
     } 
    ] 
    }, 
    { 
    "label": { 
     "en": "Community" 
    }, 
    "icon": "/images/nav/community.png", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "Latest" 
     }, 
     "link": "/community", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Best of" 
     }, 
     "link": "/community/highlight", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Discussion Boards" 
     }, 
     "link": "http://forum.slooh.askmp.ca/", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Rankings" 
     }, 
     "link": "/community/rankings", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Full Listings" 
     }, 
     "link": "/community/listings", 
     "type": "basic" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "label": { 
      "en": "Hot this Month" 
     }, 
     "type": "basic-loaded", 
     "datasource": "/community/hot" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "type": "component", 
     "component": "nav", 
     "datasource": "/data/nav" 
     }, 
     { 
     "type": "custom", 
     "content": "[social media HTML]" 
     } 
    ] 
    }, 
    { 
    "label": { 
     "en": "About" 
    }, 
    "icon": "/images/nav/about.png", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "Our Values" 
     }, 
     "link": "/about", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "In the News" 
     }, 
     "link": "/about/media", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "The Team" 
     }, 
     "link": "/about/#team", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Guests" 
     }, 
     "link": "/about/#guests", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Partners" 
     }, 
     "link": "/about/#partners", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Media Kit" 
     }, 
     "link": "/about/media", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Contact Us" 
     }, 
     "link": "/about/#contact", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Upcoming Shows" 
     }, 
     "type": "components", 
     "component": "navShow", 
     "datasource": "/data/shows/upcoming?limit=1" 
     } 
    ] 
    }, 
    { 
    "label": { 
     "en": "Help" 
    }, 
    "icon": "/images/nav/help.png", 
    "link": "/", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "New here?" 
     }, 
     "link": "/about", 
     "type": "basic" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "label": { 
      "en": "Guides" 
     }, 
     "link": "/help", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Troubleshooting" 
     }, 
     "link": "/help/#troubleshooting", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Practice Activities" 
     }, 
     "link": "/help#practice", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Image Management" 
     }, 
     "link": "/help/images", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Photography 101" 
     }, 
     "link": "/help/photography", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "What’s What?" 
     }, 
     "link": "/community/whats", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Hints and Tips" 
     }, 
     "link": "/help/#hints", 
     "type": "basic" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "label": { 
      "en": "Trouble Logging In?" 
     }, 
     "link": "/help/account", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Pricing Tiers" 
     }, 
     "link": "/help/#account", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Account FAQs" 
     }, 
     "link": "/help/#account", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Shows FAQs" 
     }, 
     "link": "/help/shows", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Reservations FAQs" 
     }, 
     "link": "/help/faqs", 
     "type": "basic" 
     }, 
     { 
     "type": "space" 
     }, 
     { 
     "label": { 
      "en": "Contact Customer Support" 
     }, 
     "link": "/help/contact", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Site Feedback" 
     }, 
     "link": "/help/contact#feedback", 
     "type": "basic" 
     } 
    ] 
    }, 
    { 
    "label": { 
     "en": "Settings" 
    }, 
    "icon": "/images/nav/settings.png", 
    "link": "/", 
    "type": "children", 
    "children": [ 
     { 
     "label": { 
      "en": "Personal Profile" 
     }, 
     "link": "/account", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Subscription Management" 
     }, 
     "link": "/account/subscription", 
     "type": "basic" 
     }, 
     { 
     "label": { 
      "en": "Alerts & Email Settings" 
     }, 
     "link": "/account/#notifications", 
     "type": "basic" 
     } 
    ] 
    } 
] 

Я пытаюсь итерацию через него, и создать вторичную навигацию из детей.

Верхний уровень достаточно прост, чтобы добраться, а второй уровень почти отсутствует. Однако при сопоставлении дочерних элементов (в GetChildren ниже) я не могу получить ничего, что является дочерним массивом, а только прямыми объектами. Таким образом, я могу получить {child.link}, но {child.label.en} возвращает ошибку. Должен ли я приближаться к этому более умным способом?

var GetChildren = React.createClass({ 
    render: function() { 
     var childlink = this.props.data.map(function (child, i){ 
     return (   
      <a key = {i} href={child.link}> {child.label.en}</a> 
     ); 
     }); 
     return (
     <li className="childlist"> 
      {childlink} 
     </li> 
    ); 
    } 
    }); 

var MenuComponent = React.createClass({ 
     getInitialState: function() {   
      return { 
      condition: [], 
      menuItem: [] 
      }; 
     }, 
     componentDidMount: function() { 
      $.get(this.props.source, function(result) { 
      var items = result; 
      if (this.isMounted()) { 
       this.setState({ 
       menuItem: items, 
       condition: false 
       }); 
      } 
      }.bind(this)); 
     }, 
     render: function(condition) { 
     PrimaryMenu = this.state.menuItem || []; 

      return (
      <aside> 
       <nav> 
       <ul> 
       {PrimaryMenu.map(function(el, i){ 
       if (el.type == "basic") { 
        var PrimaryMenuLink = el.link; 
       } else { 
        PrimaryMenuLink = '/' +el.label.en.toLowerCase(); 
       }    
        return <li key={i}> <a data-nav={'nav-' + el.label.en.toLowerCase()}> 
        {el.label.en}</a></li> 

       })} 
       </ul> 
       </nav> 
       {PrimaryMenu.map(function(el, i){ 
       if (el.type == "children") { 
        return <section key={i} id={'nav-' + el.label.en.toLowerCase()}><ul><GetChildren data={el.children}/> </ul></section> 
       }    

       })} 

       </aside>   
     ); 
     } 
     }); 
+0

Какую ошибку вы получаете при вызове {child.label.en}. – hyde

+0

@ dilettante В ваших данных у некоторых 'children' нет свойства label. Вы хотите показать только детей, где есть свойство label? –

+0

@hyde: Uncaught TypeError: Невозможно прочитать свойство 'en' undefined – dilettante

ответ

1

Проблема может исходить от некоторых из JSon узлов, которые не имеют label свойство. Как этот узел:

{ 
    "type": "space" 
}, 

В результате, он будет генерировать «не может прочитать свойство не определено» на label собственности при чтении en.

Необходимо проверить все узлы children. label существует. Также проверьте link, чтобы избежать получения undefined как href реквизита

+0

Это была проблема. Спасибо. Я часами гонялся за этим ... тьфу! – dilettante