【问题标题】:Excluding <Header /> component on a specific page with react-router使用 react-router 排除特定页面上的 <Header /> 组件
【发布时间】:2018-12-14 12:44:38
【问题描述】:

这是一个有效的代码:

const AppRouter = () => (
<BrowserRouter>
  <div>
    <Header />
    <Switch>
      <Route path="/" component={DashboardPage} exact={true} />
      <Route path="/:id" component={ViewerPage} /> // <-- Exclude Header component from this page
      <Route path="/create" component={CreatePage} />
      <Route path="/edit/:id" component={EditPage} />
      <Route path="/help" component={HelpPage} />
      <Route component={NotFoundPage} />
    </Switch>
  </div>
</BrowserRouter>
);

export default AppRouter;

我似乎无法弄清楚如何从 ViewerPage 组件页面中排除 Header 组件。有没有办法做到这一点?

【问题讨论】:

  • 用某些条件包装&lt;Header /&gt; 组件...
  • @Rayon,看起来怎么样?
  • 类似URL === SOMETHING ? null : &lt;Header /&gt;
  • 组件在什么条件下出现/不出现?
  • 仅在一条特定路线上排除它? {location.pathname !== '/route-to-exclude-header' &amp;&amp; &lt;Header /&gt;} 如果你想在多个路由上排除,请创建一组排除路径,然后 {exclusionArray.indexOf(location.pathname) &gt; 0 &amp;&amp; &lt;Header/&gt;} 使用 react-router 包提供的 withRouter HoC 将 location 注入到您的组件中。

标签: javascript reactjs react-router


【解决方案1】:

在我上一个项目中有完全相同的要求,我采用了将标头拆分为自己的组件并使用 React Fragments 的方法。惯用语!

import React, { Fragment } from 'react'
// ...

const App = () => (
  <div>
    <Switch>
      <Route path='/no-header-route' component={NoHeaderComponent} />   // Route without header
      <Fragment>            // This is the key
        <Header/>           // Header is in its own component
        <Route path='/route-1' component={Comp1}/>  // Route with header
        <Route path='/route-2' component={Comp2}/>  // Route with header
      </Fragment>
    </Switch>
  </div>
)

【讨论】:

  • 迄今为止最优雅的解决方案!正是我想要的,干得好!
  • 正是解决难题的最优雅的答案。你的回答拯救了我一整天。谢谢
  • 你的方法是在每个组件中保持渲染 404page。有没有办法防止这种情况发生?
  • 如果有人阅读此评论,我想在这里再补充一点,就我而言,如果我添加 收盘价下方
【解决方案2】:

react-router 包提供的withRouter 高阶组件将使您能够访问位置对象。一旦你有了它,你可以通过短路有条件地呈现标题。

import {withRouter} from 'react-router'

const App = ({location}) => (
  <div>
    {location.pathname !== '/exclusion-path' && <Header/>}
    <Switch>
      ...
    </Switch>
  </div>
)

export default withRouter(App)

或在多个路径上排除...

const exclusionArray = [
  '/path-one',
  '/another-path',
]

const App = ({location}) => (
  <div>
    {exclusionArray.indexOf(location.pathname) < 0 && <Header/>}
    <Switch>
      ...
    </Switch>
  </div>
)

如果您正在做任何严肃的事情,我建议您使用上下文 api 并在上下文提供的值上短路。如果是这种情况,并且您需要一些指导,我很乐意向您解释。

附:如果你想用 alpha Hooks API 来做这件事,我会非常兴奋。

编辑:解决常见问题。

将您的路由器移到 App 组件之外。

import {BrowserRouter as Router} from 'react-router-dom'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <Router>
    <App/>
  </Router>,
  document.getElementById('render-target')
)

【讨论】:

  • 这就是我得到的...Uncaught Error: You should not use &lt;Route&gt; or withRouter() outside a &lt;Router&gt;
  • 将您的 &lt;Router/&gt; 移出 App 组件。参考编辑。
  • 我正在尝试使用上下文 API,方法是使用带有 updateHeader 函数的 HeaderConsumer/HeaderProvider 来向标题添加元素,但我认为我使用的 API 错误。有什么建议@KyleRichardson?
【解决方案3】:

1- 类似,在 Header.js 中

  import {withRouter} from 'react-router-dom';

        class Header extends Component {
          render() {
            if (this.props.location.pathname === '/') {
              return null
            }
            return (
              // other stuff
            );
          }
        }
  export default withRouter(Header);

注意,withRouter 可以随着不同的 React 路由器版本而不同。但是思路是一样的:用ViewerPage的路径名检查你的路径名,如果是路径就不要显示Header...

2- 其他方法是用“redux”做同样的事情

所以每当加载 ViewerPage 时,调度一个动作。 在 ViewerPage.js 中

class ViewerPage extends Component {
          componentDidMount() {
            this.props.updateShouldDisplayHeader(false);
          }
          componentWillUnmount(){
             this.props.updateShouldDisplayHeader(true);
           }
        }

在 Header.js 中

class Header extends Component {
          render() {
            if(!this.props.shouldDisplayHeader) {
               return null;
            }
            return (
              // other stuff
            );
          }
        }

我想你已经知道如何在 redux 上创建 action 和使用 reducers

【讨论】:

  • 他想有条件地渲染标题。您可以在将呈现标题的包含组件中将其短路。
【解决方案4】:

在您的路由器文件中,在 &lt;Switch&gt; 之前调用 useRouteMatch()

export Routes = (
{useRouteMatch("/specific-route")?.isExact ? (
          <Header />
        ) : null}

<Switch>
  <Route path="other/path" component={Other}
  ...
</Switch>
);

或者,致电withRouter() 以直接访问matchlocationhistory

export const AuthenticatedRoutes = withRouter(() => (
  {location.pathname !== `/special-url` ? (
    <Header />
  ) : null}

  <Route path="/special-url" component={Special}
  <Route path="/other" component={Other} 
));

export Routes = (
  {useRouteMatch("/specific-route")?.isExact ? (
    <Header />
  ) : null}
            
  <Switch>
    <Route component={AuthenticatedRoutes}          
  </Switch>
);
     

【讨论】:

    猜你喜欢
    • 2018-10-14
    • 2022-10-23
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多