React:隐藏特定路由上的组件

IT技术 reactjs react-router react-css-modules
2021-03-31 04:26:25

新react:

我有一个<Header />组件,我只想在用户访问特定页面时隐藏它

到目前为止,我设计我的应用程序的方式<Header />导航时不重新渲染组件,只有页面内容,所以它提供了非常流畅的体验。

我试图为每条路线重新渲染标题,这样可以轻松隐藏,但每次导航时都会出现丑陋的重新渲染故障。

所以基本上,有没有办法只在进出特定路线时重新渲染组件?

如果不是,那么实现这一目标最佳实践是什么?

应用程序.js:

class App extends Component {

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

主要.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>
);
4个回答

我也是 React 的新手,但遇到了这个问题。react-router已接受答案的一种基本替代方法是使用withRouter,它包装您要隐藏的组件并为其提供locationprop(等等)。

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

请注意文档中的警告

withRouter 不会像 React Redux 的 connect 那样订阅状态更改的位置更改。相反,在位置更改从组件传播出去后重新渲染。这意味着 withRouter 不会在路由转换上重新渲染,除非其父组件重新渲染。

尽管如此,这种方法似乎对我来说适用于与 OP 非常相似的用例。

从 React Router 5.1 开始,可以使用钩子 useLocation()
2021-06-14 04:26:25

从 React Router 5.1 开始,有一个钩子 useLocation,它可以让你轻松访问当前位置。

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

function HeaderView() {
  let location = useLocation();
  console.log(location.pathname);
  return <span>Path : {location.pathname}</span>
}
这个答案让我不再为这个问题挠头。谢谢!
2021-06-09 04:26:25

您可以将其添加到所有路由(通过声明一个非精确路径)并将其隐藏在您的特定路径中:

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

然后在Header渲染方法中:

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

  if(url.startWith('/your-no-header-path') {
    return null;
  } else {
    // your existing render login
  }
}
通常 path='/' 是一个 webapp 的主页。我认为将组件作为 Layout 组件更有意义,并且该组件内部应该是显示标题或不显示标题的逻辑。
2021-05-28 04:26:25
谢谢。我确实用更多细节编辑了我的问题……那个解决方案仍然适用吗?
2021-05-29 04:26:25

您可以依靠 state 进行重新渲染。

如果您从路线导航,shouldHidethis.setState({ hide: true })

您可以<Header>使用条件将您的内容包装在渲染中:

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

或者你可以使用一个函数:

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

在渲染方法中:

{this._header()}

我还没有尝试过 react-router,但这样的事情可能会奏效:

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

并且需要手动调用 Art 内部的函数:

this.props.hideHeader()

我有点不清楚你在这里的路线。你在某处更改内容吗?当你点击路线时会发生什么?
2021-05-23 04:26:25
我第一次使用路由器......我决定将所有页面内容放在 <main> 中,并使用 Router 切换内容path="/" component={Home}......path="/about" component={About}等等......如果我不想摆脱 <header> 会很好用只在一条特定的路线上……所以我猜这也是一个设计问题
2021-05-30 04:26:25
我确实用一些代码编辑了我的问题,所以我设计布局和路由的方式更加清晰。也许问题来自那个......所以,我将不得不从 <Art /> 组件更新应用程序状态..那是我想隐藏标题的那个......然后将状态设置为 hide:false在所有其他路线?
2021-06-06 04:26:25
我想我必须研究 Context API 或 Redux 才能做到这一点,对吗?好吧,也许不是 Redux 只是为了这个......
2021-06-13 04:26:25
你能链接路由器包吗?我以前没有使用过路由器,所以这可能不适用。但是您可以做的是将修改 App 的 Header 状态的函数传递给路由。并让孩子调用该函数并直接修改父母的标题状态。
2021-06-20 04:26:25