在本文中,我们将给您介绍关于ReactRouterv4呈现多个路由的详细内容,并且为您解答react多级路由的相关问题,此外,我们还将为您提供关于ReactRouter4嵌套路由未呈现、ReactRo
在本文中,我们将给您介绍关于React Router v4呈现多个路由的详细内容,并且为您解答react 多级路由的相关问题,此外,我们还将为您提供关于React Router 4嵌套路由未呈现、React Router v4 & v5 拦截器(钩子)、静态路由、route-view 实现、React Router v4 - 如何获取当前路由?、React Router V4 正式版发布,React 路由解决方案的知识。
本文目录一览:- React Router v4呈现多个路由(react 多级路由)
- React Router 4嵌套路由未呈现
- React Router v4 & v5 拦截器(钩子)、静态路由、route-view 实现
- React Router v4 - 如何获取当前路由?
- React Router V4 正式版发布,React 路由解决方案
React Router v4呈现多个路由(react 多级路由)
我正在创建SPA,并尝试使用react-router-dom
软件包版本在应用程序中设置“路由” 4.1.1
。
我的路线定义如下:
<BrowserRouter> <div> <Route exact path="/" component={Login} /> <Route path="/login" component={Login} /> <Route path="404" component={NotFound} /> <Route path="*" component={NotFound} /> </div></BrowserRouter>
基本上,我想设置路由,以便对未定义路由的页面的任何请求都转到{NotFound}
组件。
如何做到这一点?上面的解决方案在请求页面时同时呈现Login
和NotFound
组件/login
。
亲切的问候
答案1
小编典典这是官方教程中的示例,如何避免呈现多条路线
import { Switch, Route } from ''react-router <Switch> <Route exact path="/" component={Home}/> <Route path="/about" component={About}/> <Route path="/:user" component={User}/> <Route component={NoMatch}/> </Switch>
React Router 4嵌套路由未呈现
我正在尝试在我的组件之一中进行嵌套路由。
这是父组件:
const App = () => ( <BrowserRouter> <Provider store={store}> <Switch> <Route exact path="/" component={Landing} /> <Route path="/contribute" component={Contribute} /> </Switch> </Provider> </BrowserRouter>);
这是子组件:
const Landing = () => ( <div> <SearchBar /> <section className="results-sctn"> <Route exact path="/" component={ArtistList} /> <Route path="/test" component={Test} /> </section> </div>);
ArtistList
可以很好地呈现/
路线,但/test
呈现完全空白的页面。知道为什么会这样吗?
答案1
小编典典发生此现象的原因是exact
在父路由上提到了一个属性
<Route exact path="/" component={Landing} />
因此,发生的事情是react-router看到了一条/test
匹配的路径,然后尝试从顶层开始进行匹配。它看到两条路线,一条是exactly/
,另一条是/contribute
。它们都不符合所需的路径,因此您会看到空白页
你需要写
<Route path="/" component={Landing} />
因此,当您执行此操作时,它将看到部分/
匹配的内容/test
,然后尝试在要查找的landing
组件中找到匹配的路由。
还更改父Route的顺序,因为Switch
会渲染第一个匹配项,并且/
是部分匹配项,/test
因此将/contribute
无法工作
您的最终代码如下所示
const App = () => ( <BrowserRouter> <Provider store={store}> <Switch> <Route path="/contribute" component={Contribute} /> <Route path="/" component={Landing} /> </Switch> </Provider> </BrowserRouter>);
React Router v4 & v5 拦截器(钩子)、静态路由、route-view 实现
前提
React Router
再 v3
版本之前 是有 onEnter
钩子函数的,也支持静态路由配置;,但到了 v4
版本后钩子函数被移除,官方说是为了将此提供给开发者,由开发者自由发挥。既然如此我们就只能自己实现,目前网上有很多版本,大多都是差不多的,这里做一个总结并深化一下。同时提供钩子函数或者vue中叫路由守卫和静态化路由配置。
钩子函数实现
钩子函数实现比较简单,只需要包装一下官方的路由即可实现,这里我们允许钩子支持 Promise
异步,就需要一个异步组件;代码如下
异步组件代码
class AsyncBeforeEnter extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
// 注意:此处component和render不会同时使用,同Route中component和render,render方法优先级要高
// 目标组件 同 <Route componet>
Component: null,
// 目标组件render 方法 同 <Route render>
render: null,
// 错误信息
error: null,
// 标记异步是否完成
completed: false
}
}
componentDidMount() {
const { beforeEnter, ...props } = this.props
// beforeEnter 钩子函数
const enter = beforeEnter({ ...props })
if (isPromise(enter)) {
// 判断是否是Promise
enter
.then(next => {
this.handleAfterEnter(next)
})
.catch(error => {
console.error(error)
this.setState({ error })
})
} else {
this.handleAfterEnter(enter)
}
}
handleAfterEnter(next) {
// 结果处理
const { route = {}, ...props } = this.props
// 如果结果是null 或者undefined 或者 true : 不做任何处理直接渲染组件
if (next === null || next === undefined || next === true) {
this.completed(route.component, route.render)
return
}
// 返回false:阻止组件的渲染
if (next === false) {
this.completed(null)
return
}
// 返回 string : 跳转的路由,类似http中302状态码
// 这里使用 React Router 的 Redirect 做跳转
if (typeof next === ''string'') {
this.completed(null, () => <Redirect to={next} from={props.location.pathname} />)
return
}
// 返回React 组件
if (typeof next === ''function'' || React.isValidElement(next)) {
this.completed(null, () => next)
return
}
// 返回 Object: 如果有 redirect=true 的属性,做跳转
// 否则使用 Route 组件渲染
if (isPlainObject(next)) {
const { redirect, ...nextProps } = next
if (redirect === true) {
this.completed(null, () => <Redirect {...nextProps} {...{ from: props.location.pathname }} />)
return
}
this.completed(() => <Route {...nextProps} />)
return
}
warn(`"${props.location.pathname} => beforeEnter"
hook return values error. expected null? undefined? true? React.Component? HTMLElement? Route props?
route props detail to see
https://reacttraining.com/react-router/web/api/Route
https://reacttraining.com/react-router/web/api/Redirect`
)
// 例外情况 阻止组件的渲染
this.completed(null)
}
/**
* 完成后改变state渲染组件:
* @param component
* @param render
*/
completed(component, render) {
this.setState({ Component: component, render, completed: true, error: null })
}
getExtraProps() {
// 去掉钩子函数,获取其他props
const { loading: Loading, beforeEnter, ...props } = this.props
return { ...props }
}
render() {
const { Component, render, error, completed } = this.state
if (!completed) {
// 未完成
return null
}
// 已完成
if (render && typeof render === ''function'') {
return render(this.getExtraProps())
}
return Component ? <Component {...this.getExtraProps()} /> : null
}
}
带有钩子函数的 Route
将其命名为 PrivateRoute
export default (route) => (
<Route
path={route.path}
exact={route.exact}
strict={route.strict}
location={route.location}
sensitive={route.sensitive}
children={route.children}
render={props => {
// beforeEnter
const { beforeEnter, ...nextProps } = route
// 如果有钩子函数,执行带有异步组件
if (route.beforeEnter && typeof route.beforeEnter === ''function'') {
return (
<AsyncBeforeEnter
beforeEnter={beforeEnter}
route={nextProps}
{...props}
{...extraProps}
/>
)
}
// 直接渲染
return (
route.render && typeof route.render ?
(
route.render({ ...props, ...extraProps, route: nextProps })
) : (
route.component ? (
<route.component
route={nextProps}
{...props}
{...extraProps}
/>
) : null
)
)
}}
/>
)
使用的时候就可以用该 Route
代替官方的
示例:
<PrivateRoute path="/" component={Example} beforeEnter={(props) => check(props) }/>
<PrivateRoute path="/user" component={User} beforeEnter={(props) => check(props) }/>
静态化路由配置,并支持钩子函数
静态化路由配置官方页给出了方案,见:react-router-config,本文的静态路由配置也是参考了该实现,并重写了其中的实现,加入钩子函数
静态路由配置
基本的静态路由表如下
// 顶级两个路由
// 一个登录
// 其他需要授权后放回
export default [
{
path: ''/example'',
key: ''example'',
component: Example,
beforeEnter(props) {
if (auth(props.localtion.pathname)) {
return true
}
return ''/login''
},
// 子路由
routes: [
{
path: ''/example1'',
key: ''example1'',
component: Example1,
}
]
},
{
path: ''/login'',
key: ''login'',
component: Login
}
]
改写钩子函数使其能渲染静态路由表=>renderRoutes
// renderRoutes
export default (routes, switchProps = {}, extraProps = {}) => {
return routes && routes.length > 0 ? (
<Switch {...switchProps}>
{
routes.map((route, i) => (
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
location={route.location}
sensitive={route.sensitive}
children={route.children}
render={props => {
// beforeEnter
const { beforeEnter, ...nextProps } = route
if (route.beforeEnter && typeof route.beforeEnter === ''function'') {
return (
<AsyncBeforeEnter
beforeEnter={beforeEnter}
route={nextProps}
{...props}
{...extraProps}
/>
)
}
return (
route.render && typeof route.render ?
(
route.render({ ...props, ...extraProps, route: nextProps })
) : (
route.component ? (
<route.component
route={nextProps}
{...props}
{...extraProps}
/>
) : null
)
)
}}
/>
))
}
</Switch>
) : null
}
使用就可以调用 renderRoutes
方法 , 该实例摘自官方示例:
const Root = ({ route }) => (
<div>
<h1>Root</h1>
{/* child routes won''t render without this */}
{renderRoutes(route.routes)}
</div>
);
const Home = ({ route }) => (
<div>
<h2>Home</h2>
</div>
);
const Child = ({ route }) => (
<div>
<h2>Child</h2>
{/* child routes won''t render without this */}
{renderRoutes(route.routes, { someProp: "these extra props are optional" })}
</div>
);
const GrandChild = ({ someProp }) => (
<div>
<h3>Grand Child</h3>
<div>{someProp}</div>
</div>
);
ReactDOM.render(
<BrowserRouter>
{/* kick it all off with the root route */}
{renderRoutes(routes)}
</BrowserRouter>,
document.getElementById("root")
);
实现类似 vue-router
里面的 route-view
功能
经过以上的处理,基本的钩子函数和静态路由就算配置完成了;功能虽然完成了,但总感觉使用上有点麻烦;确实,有没有类似 vue-router
中的 route-view
这种的一步到位的呢?好的,安排。。。
这里需要用到 React context
在 v16
以前这是不推荐的,不过现在已经成熟了,可以大胆的用了;如果不知道怎么用和什么原理可以 去这里 补一下知识
这里还有一个很关键的地方,看图划重点:
可以重复使用,内部的值会覆盖外层的值,这样我们就可以多层路由嵌套了;
创建 context
import React from ''react''
const RouteContext = React.createContext([])
// devtool 中使用
RouteContext.displayName = ''RouteViewContext''
export const RouteProvider = RouteContext.Provider
export const RouteConsumer = RouteContext.Consumer
创建 RouteView
import { RouteConsumer } from ''./context''
import renderRoutes from ''./renderRoutes''
//RouteView
export default () => {
return (
<RouteConsumer>
{/* 使用静态路由渲染 */}
{/* ruotes 由RouteProvider 提供 */}
{routes => renderRoutes(routes)}
</RouteConsumer>
)
}
再次改写 renderRoutes
, 使其能够渲染下级路由
import { RouteProvider } from ''./context''
// renderRoutes
export default (routes, switchProps = {}, extraProps = {}) => {
return routes && routes.length > 0 ? (
<Switch {...switchProps}>
{
routes.map((route, i) => (
<Route
key={route.key || i}
path={route.path}
exact={route.exact}
strict={route.strict}
location={route.location}
sensitive={route.sensitive}
children={route.children}
render={props => {
checkProps(props)
// beforeEnter
const { beforeEnter, ...nextProps } = route
// RouteProvider 提供下级路由所需的数据
if (route.beforeEnter && typeof route.beforeEnter === ''function'') {
return (
<RouteProvider value={route.routes}>
<AsyncBeforeEnter
beforeEnter={beforeEnter}
route={nextProps}
{...props}
{...extraProps}
/>
</RouteProvider>
)
}
return (
<RouteProvider value={route.routes}>
{
route.render && typeof route.render ?
(
route.render({ ...props, ...extraProps, route: nextProps })
) : (
route.component ? (
<route.component
route={nextProps}
{...props}
{...extraProps}
/>
) : null
)
}
</RouteProvider>
)
}}
/>
))
}
</Switch>
) : null
}
使用
在入口js添加代码如下
import { RouteProvider, RouteView } from ''../router''
// 静态路由
const routes = [
// 略。。。
]
class App extends React.PureComponent {
// 略。。。
render() {
return (
// 略。。。
// 提供顶层路由即可
// 下级路由 renderRoutes 处理
<RouteProvider value={routes}>
<RouteView />
</RouteProvider>
// 略。。。
)
}
}
export default App
二级路由使用
class Example extends React.PureComponent {
// 略。。。
render() {
// 此处便不需要再提供routes了
// 在 renderRoutes 已经由 RouteProvider 提供了
return (
<div>
Example
<RouteView />
</div>
)
}
}
export default Example
通过以上努力,我们就具备了静态路由、钩子函数、类似 vue-router
中 router-view
;
最终的努力的结果:
- 方便鉴权
- 路由方便管理
- 多层级路由一个组件即可实现渲染
原文出处:React Router v4 & v5 拦截器(钩子)、静态路由、route-view 实现
参考文章
- https://reacttraining.com/react-router/web/guides/quick-start
- https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config
- https://github.com/mirrorjs/mirror/issues/78
- https://stackoverflow.com/questions/50928349/react-router-4-how-to-wait-for-a-promise-to-resolve-inside-render-method-of-ro
- https://juejin.im/post/5d2d32a9f265da1b8b2b90c7
- https://zh-hans.reactjs.org/docs/context.html
React Router v4 - 如何获取当前路由?
我想显示一个title
以<AppBar />
某种方式从当前路由传入的 in。
在 React Router v4 中,如何将<AppBar />
当前路由传递到它的title
prop 中?
<Router basename=''/app''> <main> <Menu active={menu} close={this.closeMenu} /> <Overlay active={menu} onClick={this.closeMenu} /> <AppBar handleMenuIcon={this.handleMenuIcon} title=''Test'' /> <Route path=''/customers'' component={Customers} /> </main> </Router>
prop
有没有办法从自定义传递自定义标题<Route />
?
答案1
小编典典在 react-router 的 5.1 版本中有一个叫做 useLocation 的钩子,它返回当前的位置对象。这在您需要知道当前 URL
的任何时候都可能有用。
import { useLocation } from ''react-router-dom''function HeaderView() { const location = useLocation(); console.log(location.pathname); return <span>Path : {location.pathname}</span>}
React Router V4 正式版发布,React 路由解决方案
React Router V4 正式版发布,该版本相较于前面三个版本有根本性变化,遵循 Just Component 的 API 设计理念。
本次升级的主要变更有:
声明式 Declarative
可组合 Composability
本次升级 React Router V4 吸取了 React 的理念:所有的东西都是 Component。因此 升级之后的 Route、Link、Switch……等都是一个普通的组件。
React Router V4 基于 Lerna 管理多个 Repository。在此代码库包括:
react-router React Router 核心
react-router-dom 用于 DOM 绑定的 React Router
react-router-native 用于 React Native 的 React Router
react-router-redux React Router 和 Redux 的集成
react-router-config 静态路由配置帮助助手
React Router V4 中文文档
今天的关于React Router v4呈现多个路由和react 多级路由的分享已经结束,谢谢您的关注,如果想了解更多关于React Router 4嵌套路由未呈现、React Router v4 & v5 拦截器(钩子)、静态路由、route-view 实现、React Router v4 - 如何获取当前路由?、React Router V4 正式版发布,React 路由解决方案的相关知识,请在本站进行查询。
本文标签: