2017-09-28 10 views
0

コンポーネントはNavLinkエレメントのセットを持っていますので、アクティブな場合にスタイルを設定できます。リアクタールータ4の一致プロパティー

セクションを手作業で開閉することもできます。

私がしたいのは、navに複数のセクションがあり、アクティブなNavLinkがある場合、セクションが開いていることです。

AdminNav.js ナビゲーションコンポーネント。基本的にNavLinkのリストです。

import React, { Component } from 'react' 
import { NavLink, withRouter } from 'react-router-dom' 
import _find from 'lodash/find' 

import '../../css/sub-nav.css' 

class AdminNav extends Component { 

    constructor(props){ 
     super(props) 

     // Shows 'admin/' at all times 
     console.log(props.match) 

     this.state = { 
      sectionRoutes: [ 
       { 
        title: 'Cart', 
        routes: [ 
         { 
          title: 'Dashboard', 
          path: '/admin', 
          exact: true 
         }, 
         { 
          title: 'View Orders', 
          path: '/admin/view-orders', 
          exact: false 
         }, 
         { 
          title: 'Cart Settings', 
          path: '/admin/settings', 
          exact: true 
         }, 
         { 
          title: 'Merchant Settings', 
          path: '/admin/merchant', 
          exact: true 
         } 
        ] 
       }, 
       { 
        title: 'Products', 
        routes: [ 
         { 
          title: 'Add Product', 
          path: '/admin/product-add', 
          exact: true 
         }, 
         { 
          title: 'Edit Product', 
          path: '/admin/product-edit', 
          exact: true 
         }, 
         { 
          title: 'Add Category', 
          path: '/admin/category-add', 
          exact: true 
         }, 
         { 
          title: 'Edit Category', 
          path: '/admin/category-edit', 
          exact: true 
         }, 
         { 
          title: 'Set Category Order', 
          path: '/admin/category-order', 
          exact: true 
         } 
        ] 
       }, 
       { 
        title: 'User', 
        routes: [ 
         { 
          title: 'Logout', 
          path: '/admin/logout', 
          exact: true 
         } 
        ] 
       } 
      ], 
      openSections: [] 
     } 
    } 

    handleSectionClick = (sectionTitle) => { 
     let titleIndex = this.state.openSections.indexOf(sectionTitle) 

     if(titleIndex > -1){ 
      this.setState({ openSections: this.state.openSections.filter((title, i) => i !== titleIndex)}) 
     }else{ 
      this.setState({ openSections: [ ...this.state.openSections, sectionTitle ] }) 
     } 
    } 

    isSectionOpen(section){ 

     const currentPath = this.props.location.pathname 

     // Section is open if routh path matches the current path OR section has been manually opened 
     // THIS DOES NOT WORK IF section is a route that has optional params (Ex. `admin/view-orders/:id?`) 
     const result = _find(section.routes, route => currentPath === route.path) || 
         _find(this.state.openSections, title => title === section.title) 

     return result 
    } 

    render() { 
     return (
      <div className="sub_nav"> 
       <div className="title">Admin Menu</div> 

       {this.state.sectionRoutes.map(section => 
        <div key={section.title} className="nav_section"> 
         <div className={'section_title' + (this.isSectionOpen(section) ? ' open' : '')} onClick={(e) => this.handleSectionClick(section.title)}>{section.title}</div> 
         <div> 
          {section.routes.map(route => 
           <NavLink key={route.title} activeClassName="active" to={route.path} exact={!!route.exact}>{route.title}</NavLink> 
          )} 
         </div> 
        </div> 
       )} 
      </div> 
     ) 
    } 
} 

export default withRouter(AdminNav) 

私はadmin/に行く場合に予想されるように、Cartセクションが表示されます。 admin/view-ordersに行くと、期待通りにCartセクションが表示されます。 しかし、admin/view-orders/123に行くとNavLink配列のパスが一致しないため、セクションにopenクラスが追加されません。

adminRoutes.js これは、すべての管理者ルートを保存するルーティングファイルです。ここに完全には示されていません。

import React from 'react' 

import AdminDashboard from './AdminDashboard' 
import AdminLogout from './AdminLogout' 
import AdminOrders from './AdminOrders' 

export default [ 
    { 
     path: "/admin", 
     exact: true, 
     render: (props) => (<AdminDashboard {...props} />) 
    }, 
    { 
     path: "/admin/logout", 
     component: AdminLogout 
    }, 
    { 
     path: "/admin/view-orders/:id?", 
     component: AdminOrders 
    }, 
    { 
     component:() => <h1 className="no-margin">Page not found</h1> 
    } 
] 

Admin.js 親管理ルート。これはAdminNavを持っており、adminRoutes.js

import React, { Component } from 'react' 
import { Switch, Route } from 'react-router-dom' 
import AdminNav from './AdminNav' 

import routes from './adminRoutes' 

class Admin extends Component { 
    render() { 
     return (
      <div className="full_body_container"> 
       <div className="sub_nav_wrapper"> 
        <div className="hbs-container-admin-nav"> 
         <AdminNav /> 
        </div> 
       </div> 
       <div className="content_wrapper"> 
        { 
         <Switch> 
          {routes.map((route, i) => <Route key={i} {...route} />)} 
         </Switch> 
        } 
       </div> 
      </div> 
     ) 
    } 
} 

export default Admin 

で説明したように、管理者、子の経路のいずれかへのルートはなりますこのについて移動する良い方法はありますか?このコンポーネントから完全に一致した実際のルートにアクセスできますか?またはこれです

+0

私はstackoverflow上のタイプミスか、ルートが動作しない理由の可能性があるシステム内のタイプかどうかはわかりません。あなたは '' admin/view-order/123'''をURLとして、 '' '/ admin/view-orders /:id?" '' 'をルートとして使います。 URLは単数形 '' 'order''で、経路は複数形に構成されています - ' '' view-orders''' –

+0

Typo。質問が更新されました。ごめんなさい! – Gurnzbot

答えて

0

私はchildren function prop of routesを使用する必要があると思います。

Routeコンポーネントは、子としての機能を取る(代わりのtraditionnaly 要素に反応。 この関数は、引数としてオブジェクトと呼ばれている。我々は{試合}プロパティであるため を探しているもの。ルートと一致した場合その値は、それがnullになり、他のルートで渡さ 古典match対象になります。この例では

class App extends Component { 
    render() { 
     return (
      <Router> 
       <div className="App"> 
        <header className="App-header"> 
         <img src={logo} className="App-logo" alt="logo" /> 
         <h1 className="App-title">Welcome to React</h1> 
         <Link to="/other">other route</Link> 
        </header> 
        <Route path="/" exact> 
         {({ match }) => { 

          return <Message /> 

         }} 
        </Route> 
        <Route path="/other"> 
         {({ match, ...props }) => { 

          console.log(match, props); 
          return <Message text={match ? "this matches" : "does not match"} /> 

         }} 
        </Route> 

       </div> 
      </Router> 
    ); 
    } 
} 

、私はいつも「その他」のルータで何かをレンダリングするルートがある場合、私はちょうどテスト一致したメッセージを更新します他のルートが一致するかどうかは決して変わりません。

関連する問題