【问题标题】:React Router 4 match property反应路由器 4 匹配属性
【发布时间】:2017-09-29 22:07:00
【问题描述】:

我有一个 AdminNav 组件,其中包含一组 NavLink 元素,因此如果它们处于活动状态,我可以设置它们的样式。

这些部分也可以手动打开/关闭以减少混乱。

我想做的是在导航中有一堆部分,如果它有一个活动的NavLink,则打开该部分。

AdminNav.js 导航组件。基本上是NavLinks 的列表。

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-ordersCart 部分正如预期的那样。 但是,如果我转到 admin/view-orders/123,则 NavLinkarray 的路径不匹配,因此该部分不会添加 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

有没有更好的方法来解决这个问题?我可以从这个组件访问实际完全匹配的路由吗?还是这个

【问题讨论】:

  • 我不确定它是否只是 stackoverflow 上的错字或系统中的类型,这可能是路由无法正常工作的原因。您有 admin/view-order/123 作为 URL 和 "/admin/view-orders/:id?" 作为路由。 url为单数order,路由配置为复数-view-orders
  • 错字。更新了问题。对不起!

标签: javascript reactjs react-router react-router-v4


【解决方案1】:

我认为您需要使用children function prop of routes

Route 组件将函数作为子函数(而不是 React 传统上的元素。 此函数以对象作为参数调用。我们在寻找什么 for 是 { match } 属性。如果路由匹配,那么它的值将是 Route 传递的经典 match 对象,否则将是 null

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

在这个例子中,我总是在“其他”路由器中渲染一些东西,我只是测试路由是否匹配并相应地更新消息。你会看到另一条路由无论匹配与否都不会改变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 2017-08-06
    • 1970-01-01
    • 2021-11-25
    • 2017-07-10
    • 2018-06-07
    • 2022-01-14
    相关资源
    最近更新 更多