【问题标题】:React: Hide a Component on a specific RouteReact:隐藏特定路由上的组件
【发布时间】:2018-11-19 12:00:06
【问题描述】:

React 新手:

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

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

我尝试为每条路线重新渲染标题,这样可以轻松隐藏,但每次导航时都会遇到难看的重新渲染故障。

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

如果不是,实现此目标的最佳做法是什么?

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

【问题讨论】:

  • 什么重新渲染故障?
  • 这就像整个应用程序重新加载。导航时闪烁 10 毫秒

标签: reactjs react-router react-css-modules


【解决方案1】:
{location.pathname !== '/page-you-dont-want' && <YourComponent />}

这将检查路径名,如果它不是您不希望组件出现的页面,则不会显示它,否则将显示它。

【讨论】:

    【解决方案2】:

    从 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>
    }
    

    【讨论】:

    • 这个答案让我对这个问题不屑一顾。谢谢!
    • 像魅力一样工作。
    【解决方案3】:

    我也是 React 新手,但遇到了这个问题。接受答案的基于react-router 的替代方案是使用withRouter,它包装您要隐藏的组件并为其提供location 道具(以及其他)。

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

    请注意来自the docs 的警告:

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

    尽管有这个警告,但这种方法似乎对我来说适用于与 OP 非常相似的用例。

    【讨论】:

    • 从 React Router 5.1 开始可以使用 hook useLocation()
    【解决方案4】:

    您可以依赖状态来进行重新渲染。

    如果您从路线shouldHide 导航,那么this.setState({ hide: true })

    您可以使用条件将&lt;Header&gt; 包装在渲染中:

    {
      !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()

    【讨论】:

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

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

    <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 的主页。我认为将组件作为布局组件更有意义,并且该组件内部应该是显示标题的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 2021-11-26
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多