如何在 React Router v4 中嵌套路由?
How to nest routes in React Router v4?
有没有办法在 React Router v4 中嵌套路由?
这个有效:
<Router basename='/app'>
<main>
<Route path='/' component={AppBar} />
<Route path='/customers' component={Customers} />
</main>
</Router>
这不是:
<Router basename='/app'>
<Route path='/' component={AppBar}>
<Route path='/customers' component={Customers} />
</Route>
</Router>
客户组件:
import React, { Component, PropTypes } from 'react'
import styled from 'styled-components'
export default class Customers extends Component {
render () {
return (
<Container>
<h1>Customers</h1>
</Container>
)
}
}
const Container = styled.section`
height: 100%;
padding: 15px;
overflow: auto;
`
你的 AppBar 组件负责渲染 Customers。要调用客户,您必须渲染 AppBar 的子项。直接嵌套在 AppBar 下的任何东西都是 AppBar 的子项。
import React from 'react';
const AppBar = ({ children }) => (
<div>
<header>
<h1> stuff </h1>
</header>
{children}
</div>
);
export default AppBar
请注意,当您访问“/”时,只有AppBar 会呈现。 AppBar 和 Customers 将在您访问“/customers”时呈现。
迄今为止我找到的最佳模式。
// main app
<div>
// not setting a path prop, makes this always render
<Route component={AppShell}/>
<Switch>
<Route exact path="/" component={Login}/>
<Route path="/dashboard" component={AsyncDashboard(userAgent)}/>
<Route component={NoMatch}/>
</Switch>
</div>
我可以继续将它嵌套在一个组件中并且一切正常,包括 hmr(如果使用 webpack,请不要忘记将 output.publicPath
设置为 "/"
)
// dashboard component
<div>
// the same way as before, not setting a path prop
// makes it render on every /dashboard/** request
<Route component={DashboardTAB}/>
<Switch>
// longer path (with same root) than others first
<Route path="/dashboard/graphs/longerpath" component={GraphForm}/>
<Route path="/dashboard/graphs" component={Graphs}/>
<Route path="/dashboard/workers" component={List}/>
<Route path="/dashboard/insert" component={InsertComponent}/>
</Switch>
</div>
我从文档中改编了这个,到目前为止似乎有效。可能遗漏了一些明显的东西,是的,这不是 v4 方式,但我们需要在一个地方定义所有路由。
function RouteNest(props){ return (
<Route exact={props.exact} path={props.path} render={ p => <props.component {...p} children={props.children}/> } />
)}
export const MainRoutes = props =>
<div className='content layout'>
<Route exact path="/" component={Landing}/>
<Route path={'/contact'} component={Contact}/>
<RouteNest path={'/thing'} component={CompoWithSub}>
<RouteNest path={'/thing/suba'} component={SubComponentA}/>
<RouteNest path={'/thing/subb'} component={SubComponentB}/>
</RouteNest>
</div>
export const CompoWithSub = props => <div>{props.children)</div>
如果有人想在不输入包装器路由前缀的情况下使用嵌套路由,我已经在 TSX 中创建了类似这样的东西:
进口:
import * as React from 'react';
import { Route, RouteComponentProps, RouteProps, Switch } from 'react-router-dom';
import Index from 'views/index';
import Login from 'views/login';
import NoMatch from 'views/no-match';
接口:
interface INestedRoutes {
nested?: string;
}
interface INestedRoute extends RouteProps, INestedRoutes {}
NestedRoute 和 NestedRoutes 包装器:
class NestedRoutes extends React.Component<INestedRoutes> {
public render() {
const childrenWithProps = React.Children.map(this.props.children, (child) => {
return React.cloneElement(
child as React.ReactElement<any>, { nested: this.props.nested },
);
})
return childrenWithProps;
}
}
const NestedRoute: React.SFC<INestedRoute> = (props: INestedRoute) => {
return <Route path={`${props.nested}${props.path}`} component={props.component} />;
};
以及包装器路由:
const MultiLanguage: React.SFC<RouteComponentProps<any>> = (props: RouteComponentProps<any>) => {
return (
<NestedRoutes nested={props.match.path} >
<NestedRoute path="/test" component={Login} />
<NestedRoute path="/no-match" component={NoMatch} />
</NestedRoutes>
);
};
export default (
<Switch>
<Route path="/:language" component={MultiLanguage}/>
<Route exact={true} path="/" component={Index} />
<Route path="/login" component={Login} />
<Route component={NoMatch} />
</Switch>
);
对于嵌套路由,我使用了一种非常简单的方法。
示例主路由器就是这样
<Router history={history}>
<Switch >
<Route path="/" component={Home}></Route>
</Switch>
</Router>
使用嵌套路由的 Inside Home 组件如下:
<div className="App">
<Navbar title="Home" links = { NavbarLinks }/>
{this.renderContentPage()}
</div>
renderContentPage 将检查 URL 并呈现嵌套路由。
<Route exact path="/" component={Page1}></Route>
<Route exact path="/page1" component={Page1}></Route>
<Route exact path='/page2' component={Page2} />
因此在 Home 组件内部渲染了 page1 和 page2 组件。
路由需要一个 children,即一个组件。
它不应该是一个新的路线。
您可以做的是将嵌套路由包含在客户组件中。
还要确保完全删除客户组件中的路由。
有没有办法在 React Router v4 中嵌套路由?
这个有效:
<Router basename='/app'>
<main>
<Route path='/' component={AppBar} />
<Route path='/customers' component={Customers} />
</main>
</Router>
这不是:
<Router basename='/app'>
<Route path='/' component={AppBar}>
<Route path='/customers' component={Customers} />
</Route>
</Router>
客户组件:
import React, { Component, PropTypes } from 'react'
import styled from 'styled-components'
export default class Customers extends Component {
render () {
return (
<Container>
<h1>Customers</h1>
</Container>
)
}
}
const Container = styled.section`
height: 100%;
padding: 15px;
overflow: auto;
`
你的 AppBar 组件负责渲染 Customers。要调用客户,您必须渲染 AppBar 的子项。直接嵌套在 AppBar 下的任何东西都是 AppBar 的子项。
import React from 'react';
const AppBar = ({ children }) => (
<div>
<header>
<h1> stuff </h1>
</header>
{children}
</div>
);
export default AppBar
请注意,当您访问“/”时,只有AppBar 会呈现。 AppBar 和 Customers 将在您访问“/customers”时呈现。
迄今为止我找到的最佳模式。
// main app
<div>
// not setting a path prop, makes this always render
<Route component={AppShell}/>
<Switch>
<Route exact path="/" component={Login}/>
<Route path="/dashboard" component={AsyncDashboard(userAgent)}/>
<Route component={NoMatch}/>
</Switch>
</div>
我可以继续将它嵌套在一个组件中并且一切正常,包括 hmr(如果使用 webpack,请不要忘记将 output.publicPath
设置为 "/"
)
// dashboard component
<div>
// the same way as before, not setting a path prop
// makes it render on every /dashboard/** request
<Route component={DashboardTAB}/>
<Switch>
// longer path (with same root) than others first
<Route path="/dashboard/graphs/longerpath" component={GraphForm}/>
<Route path="/dashboard/graphs" component={Graphs}/>
<Route path="/dashboard/workers" component={List}/>
<Route path="/dashboard/insert" component={InsertComponent}/>
</Switch>
</div>
我从文档中改编了这个,到目前为止似乎有效。可能遗漏了一些明显的东西,是的,这不是 v4 方式,但我们需要在一个地方定义所有路由。
function RouteNest(props){ return (
<Route exact={props.exact} path={props.path} render={ p => <props.component {...p} children={props.children}/> } />
)}
export const MainRoutes = props =>
<div className='content layout'>
<Route exact path="/" component={Landing}/>
<Route path={'/contact'} component={Contact}/>
<RouteNest path={'/thing'} component={CompoWithSub}>
<RouteNest path={'/thing/suba'} component={SubComponentA}/>
<RouteNest path={'/thing/subb'} component={SubComponentB}/>
</RouteNest>
</div>
export const CompoWithSub = props => <div>{props.children)</div>
如果有人想在不输入包装器路由前缀的情况下使用嵌套路由,我已经在 TSX 中创建了类似这样的东西:
进口:
import * as React from 'react';
import { Route, RouteComponentProps, RouteProps, Switch } from 'react-router-dom';
import Index from 'views/index';
import Login from 'views/login';
import NoMatch from 'views/no-match';
接口:
interface INestedRoutes {
nested?: string;
}
interface INestedRoute extends RouteProps, INestedRoutes {}
NestedRoute 和 NestedRoutes 包装器:
class NestedRoutes extends React.Component<INestedRoutes> {
public render() {
const childrenWithProps = React.Children.map(this.props.children, (child) => {
return React.cloneElement(
child as React.ReactElement<any>, { nested: this.props.nested },
);
})
return childrenWithProps;
}
}
const NestedRoute: React.SFC<INestedRoute> = (props: INestedRoute) => {
return <Route path={`${props.nested}${props.path}`} component={props.component} />;
};
以及包装器路由:
const MultiLanguage: React.SFC<RouteComponentProps<any>> = (props: RouteComponentProps<any>) => {
return (
<NestedRoutes nested={props.match.path} >
<NestedRoute path="/test" component={Login} />
<NestedRoute path="/no-match" component={NoMatch} />
</NestedRoutes>
);
};
export default (
<Switch>
<Route path="/:language" component={MultiLanguage}/>
<Route exact={true} path="/" component={Index} />
<Route path="/login" component={Login} />
<Route component={NoMatch} />
</Switch>
);
对于嵌套路由,我使用了一种非常简单的方法。
示例主路由器就是这样
<Router history={history}>
<Switch >
<Route path="/" component={Home}></Route>
</Switch>
</Router>
使用嵌套路由的 Inside Home 组件如下:
<div className="App">
<Navbar title="Home" links = { NavbarLinks }/>
{this.renderContentPage()}
</div>
renderContentPage 将检查 URL 并呈现嵌套路由。
<Route exact path="/" component={Page1}></Route>
<Route exact path="/page1" component={Page1}></Route>
<Route exact path='/page2' component={Page2} />
因此在 Home 组件内部渲染了 page1 和 page2 组件。
路由需要一个 children,即一个组件。 它不应该是一个新的路线。 您可以做的是将嵌套路由包含在客户组件中。
还要确保完全删除客户组件中的路由。