根据路径处理条件组件渲染的正确方法?

flp*_*ppv 6 reactjs react-router react-router-v4 react-router-dom react-router-v5

我在Web和SO上搜索了很多内容,在reactiflux聊天中询问,但是没有找到一种干净的,没有漏洞的方法来根据路径/路径呈现某些组件。

假设我有<Header />应该显示在某些页面上的内容,应该在其他页面上隐藏的内容。

确保可以在Header组件中使用此字符串

if (props.location.pathname.indexOf('/pageWithoutAHeader') > -1) return null
Run Code Online (Sandbox Code Playgroud)

如果/pageWithoutAHeader是唯一的,那完全没问题。如果我需要5页具有相同的功能,它将变为:

if (props.location.pathname.indexOf('/pageWithoutAHeader1') > -1) return null
if (props.location.pathname.indexOf('/pageWithoutAHeader2') > -1) return null
if (props.location.pathname.indexOf('/pageWithoutAHeader3') > -1) return null
Run Code Online (Sandbox Code Playgroud)

是的,我可以将路由存储在数组中并编写一个循环,这将更可重用代码。但这是处理此用例的最好,最优雅的方法吗?

我认为这甚至可能是错误的,例如,如果我不使用路由呈现页面的标题,/xyz而我却使用带有UUID的路由,例如/projects/:idid=xyzfoo/projects/xyzfoo则不会显示标题,但应该显示标题。

Uji*_*T34 5

您可以首先列出没有标题的所有路由,然后在附加交换机中将其他路由分组:

...
<Switch>
  <Route path="/noheader1" ... />
  <Route path="/noheader2" ... />
  <Route path="/noheader3" ... />
  <Route component={HeaderRoutes} />
</Switch>
...

HeaderRoutes = props => (
  <React.Fragment>
    <Header/>
    <Switch>
      <Route path="/withheader1" ... />
      <Route path="/withheader2" ... />
      <Route path="/withheader3" ... />
    </Switch>
  </React.Fragment>
)
Run Code Online (Sandbox Code Playgroud)

文档

没有路径的路由总是匹配的。

不幸的是,此解决方案可能存在“未找到”页面的问题。它应该放在 的末尾,HeaderRoutes并且会以Header.

Dhara的解决方案没有这样的问题。但Switch如果 React Router 内部结构发生变化,它可能无法很好地工作:

a 的所有子元素<Switch>都应该是<Route><Redirect>元素。只会呈现与当前位置匹配的第一个孩子。

HOC overRoute不是一个Route本身。但它应该工作正常,因为事实上目前的代码库预计任何React.Element具有相同的道具语义<Route><Redirect>拥有。


Dha*_*ola 5

为了实现DRY规则(避免代码重复)并根据路由实现条件渲染,您应采用以下结构:

步骤1)创建layout(HOC),该布局将返回给定的组件<Header/>并导出

import React from "react"
import { Route } from "react-router-dom"
import Header from "./Header"

export const HeaderLayout = ({component: Component, ...rest}) => (
    <Route {...rest} render={(props) => (
        <>
            <Header/>
            <Component {...props} />
        </>
    )} />
)
Run Code Online (Sandbox Code Playgroud)

步骤2)导入布局并使用它

import React, { Component } from 'react'
import { BrowserRouter, Route, Switch } from "react-router-dom"
import Test1 from './Test1';
import Test2 from './Test2';
import { HeaderLayout } from './HeaderLayout';

export default class Main extends Component {
    render() {
        return (
            <BrowserRouter>
                <Switch>
                    <HeaderLayout path="/test1" component={Test1} />
                    <Route path="/test2" component={Test2}/>
                </Switch>
            </BrowserRouter>

        )
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

路径测试1

路径测试2

结论:

因此,每当您希望将标题组件与路由定义的组件一起使用时,<HeaderLayout />并且如果您不想使用标题,则只需<Route />在页面中隐藏标题即可。