使用react-router排除特定页面上的<header>组件

时间:2018-12-14 12:44:39

标签: javascript reactjs react-router

这是一个有效的代码:

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组件。有什么办法吗?

4 个答案:

答案 0 :(得分:2)

react-router软件包提供的withRouter高阶组件将使您可以访问location对象。一旦有了,就可以通过短路有条件地渲染标题。

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

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

P.S。如果您想使用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')
)

答案 1 :(得分:0)

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上创建动作并使用reducer

答案 2 :(得分:0)

在我的上一个项目中有完全相同的要求,因此我采用了将标头拆分为自己的组件并使用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>
)

答案 3 :(得分:0)

在路由器文件中,在<Switch>之前调用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>
);