React: Hide a Component on a specific Route

寵の児 提交于 2020-07-17 10:16:41

问题


New to React:

I have a <Header /> Component that I want to hide only when the user visit a specific page.

The way I designed my app so far is that the <Header /> Component is not re-rendered when navigating, only the page content is, so it gives a really smooth experience.

I tried to re-render the header for every route, that would make it easy to hide, but I get that ugly re-rendering glitch each time I navigate.

So basically, is there a way to re-render a component only when going in and out of a specific route ?

If not, what would be the best practice to achieve this goal ?

App.js:

class App extends Component {

  render() {
    return (
      <BrowserRouter>
        <div className="App">
          <Frame>
            <Canvas />
            <Header />
            <Main />
            <NavBar />
          </Frame>
        </div>
      </BrowserRouter>
    );
  }
}

Main.js:

const Main = () => (
  <Switch>
    <Route exact activeClassName="active" path="/" component={Home} />
    <Route exact activeClassName="active" path="/art" component={Art} />
    <Route exact activeClassName="active" path="/about" component={About} />
    <Route exact activeClassName="active" path="/contact" component={Contact} />
  </Switch>
);

回答1:


I'm new to React too, but came across this problem. A react-router based alternative to the accepted answer would be to use withRouter, which wraps the component you want to hide and provides it with location prop (amongst others).

import { withRouter } from 'react-router-dom';    
const ComponentToHide = (props) => {
  const { location } = props;
  if (location.pathname.match(/routeOnWhichToHideIt/)){
    return null;
  }

  return (
    <ComponentToHideContent/>
  )
}

const ComponentThatHides = withRouter(ComponentToHide);

Note though this caveat from the docs:

withRouter does not subscribe to location changes like React Redux’s connect does for state changes. Instead, re-renders after location changes propagate out from the component. This means that withRouter does not re-render on route transitions unless its parent component re-renders.

This caveat not withstanding, this approach seems to work for me for a very similar use case to the OP's.




回答2:


You could add it to all routes (by declaring a non exact path) and hide it in your specific path:

<Route path='/' component={Header} /> // note, no exact={true}

then in Header render method:

render() {
  const {match: {url}} = this.props;

  if(url.startWith('/your-no-header-path') {
    return null;
  } else {
    // your existing render login
  }
}



回答3:


You can rely on state to do the re-rendering.

If you navigate from route shouldHide then this.setState({ hide: true })

You can wrap your <Header> in the render with a conditional:

{
  !this.state.hide &&
  <Header>
}

Or you can use a function:

_header = () => {
  const { hide } = this.state
  if (hide) return null
  return (
    <Header />
  )
}

And in the render method:

{this._header()}

I haven't tried react-router, but something like this might work:

class App extends Component {

  constructor(props) {
    super(props)
    this.state = {
      hide: false
    }
  }

  toggleHeader = () => {
    const { hide } = this.state
    this.setState({ hide: !hide  })
  }

  render() {

    const Main = () => (
      <Switch>
        <Route exact activeClassName="active" path="/" component={Home} />
        <Route
          exact
          activeClassName="active"
          path="/art"
          render={(props) => <Art toggleHeader={this.toggleHeader} />}
        />
        <Route exact activeClassName="active" path="/about" component={About} />
        <Route exact activeClassName="active" path="/contact" component={Contact} />
      </Switch>
    );

    return (
      <BrowserRouter>
        <div className="App">
          <Frame>
            <Canvas />
            <Header />
            <Main />
            <NavBar />
          </Frame>
        </div>
      </BrowserRouter>
    );
  }
}

And you need to manually call the function inside Art:

this.props.hideHeader()




回答4:


Since React Router 5.1 there is the hook useLocation, which lets you easily access the current location.

import { useLocation } from 'react-router-dom'

function HeaderView() {
  let location = useLocation();
  console.log(location.pathname);
  return <span>Path : {location.pathname}</span>
}


来源:https://stackoverflow.com/questions/50777333/react-hide-a-component-on-a-specific-route

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!