如何使用 GatsbyJS 根据路由渲染组件?

Posted

技术标签:

【中文标题】如何使用 GatsbyJS 根据路由渲染组件?【英文标题】:How to render a component according to the route using GatsbyJS? 【发布时间】:2019-12-17 23:17:42 【问题描述】:

我正在使用GatsbyJS,我正在尝试根据 URL 的路由呈现不同的header

例子:

mydomain.com/ => 应该渲染HeaderLanding

mydomain.com/blog => 应该渲染HeaderMain

有谁知道根据layout.js文件中的路由创建条件渲染以显示组件的正确方法吗?

感谢您的支持。

// layout.js

import React from "react"
import PropTypes from "prop-types"
import HeaderLanding from "./header-landing"
import HeaderMain from "./header-main"
import Footer from "./footer"

const Layout = ( children ) => 
  return (
    <>
      <Header/>
      <div className="content-wrapper">
        <main>children</main>
      </div>
      <Footer/>
    </>
  )


export default Layout

【问题讨论】:

嗨,Olivier,阅读这个 - ***.com/help/someone-answers,然后尝试结束这个问题。 【参考方案1】:

@ravibagul91 回答的差不多,但是 Gatsby 没有使用 react-router-dom

如果Layout 是一个页面组件,Gatsby 将传递一个location 属性。您可以提取 location.pathname 并在那里应用您的逻辑

const Layout = ( children, location ) => 
  const isMain = location.pathname === 'your-path'

  return (
    <>
       isMain ? <HeaderMain> : <HeaderLanding> 
      <div className="content-wrapper">
        <main>children</main>
      </div>
      <Footer/>
    </>
  )


export default Layout

如果Layout不是页面组件,可以从@reach/router导入HOCLocation

import  Location  from '@reach/router' // gatsby's dep

const Layout = ( children ) => 
  return (
    <Location>
       ( location ) => (
         ...
       )
    </Location>

  )

或者简单地将 location 属性从 Gatsby 页面组件传递给每个页面的该组件:

import Layout from '../components/layout'

export default ( location ) => (
  <Layout location=location>
    ...
  </Layout>
)

【讨论】:

【参考方案2】:

您可以使用withRouter HOC 的location 对象。

import  withRouter  from 'react-router-dom';

const Layout = ( children, location ) => 

  return (
    <>
      location.pathname.split('/')[1] ==="blog" ? <HeaderMain /> : <HeaderLanding /> 
      <div className="content-wrapper">
        <main>children</main>
      </div>
      <Footer/>
    </>
  )


export default withRouter(Layout)

更新

Gatsby v2 已将路由器从 react-router 切换到 @reach/router

来自docs,

在 v1 中,布局组件可以访问历史记录、位置和匹配道具。在 v2 中,只有页面可以访问这些道具。如果您在布局组件中需要这些道具,请从页面中传递它们。

所以你的Layout 组件应该是,

const Layout = ( children, location ) => 

  return (
    <>
      location.pathname.split('/')[1] ==="blog" ? <HeaderMain /> : <HeaderLanding /> 
      <div className="content-wrapper">
        <main>children</main>
      </div>
      <Footer/>
    </>
  )


export default Layout

你的Page 组件应该是,(只是示例)

import React from "react"
import Layout from "../components/layout"
export default props => (
  <Layout location=props.location> //Pass location here
    <div>Hello World</div>
  </Layout>
)

或者你可以使用Location

通常您只能访问 Route Components 中的位置,Location 使用子渲染道具在您的应用中的任何位置提供位置。

<Location>
  props => 
    props.location
    props.navigate
  
</Location>

// usually folks use some destructuring
<Location>
  ( location )=> 
    // ...
  
</Location>

【讨论】:

以上是关于如何使用 GatsbyJS 根据路由渲染组件?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不根据路由渲染组件?

如何使用新的反应路由器钩子测试组件?

如何使用 react-router-dom 卸载路由更改上的组件而不是重新渲染 [重复]

如何添加将使用 react-router-dom 渲染组件的路由?

我是第一次使用路由器。如何在第一个组件打开时自动渲染第一个组件?

React:如何停止重新渲染组件或对同一路由更改路由器进行 API 调用