【问题标题】:Passing location and pageContext from page to child components in Gatsby在 Gatsby 中将 location 和 pageContext 从页面传递给子组件
【发布时间】:2020-09-15 08:09:17
【问题描述】:

我的 Gatsby 网站页面布局如下所示。

const Container = ({location, children, pageContext}) => {
  return (
    <>
      <Header location={location} />
      <Breadcrumbs pageContext={pageContext} />
      {children}
      <Footer />
    </>
  )
}

我需要将页面中的locationpageContext 传递给子组件。我尝试将locationpageContext 添加到DataProvider,如下所示:

export const DataContext = React.createContext();

const DataProvider = ({ children, location, pageContext }) => {
  return (
    <DataContext.Provider value={{
      location,
      pageContext
    }}>
      {children}
    </DataContext.Provider>
  )
};

export default DataContext
export { DataProvider }

然后我在gatsby-ssr.jsgatsby-browser.js 中使用DataProvider,如下所示:

export const wrapRootElement = ({ element }) => (
  <ThemeProvider theme={theme}>
    <DataProvider>
      {element}
    </DataProvider>
  </ThemeProvider>
);

在子组件中:

const HeaderLinks = () => {
  return (
    <DataContext.Consumer>
      {
        context => (
          <Menu
            theme="light"
            mode="horizontal"
            selectedKeys={[context.location.pathname]}
          >
            <Menu.Item key={key}>
              <Link to={url}>{name}</Link>
            </Menu.Item>
          </Menu>
        )
      }
    </DataContext.Consumer>
  )
}

但它似乎不起作用,因为当我移动到另一个页面时它没有得到更新。 (我也有wrapPageElementContainer,可能就是这个原因。)

如何将locationpageContext 传递给子组件?使用 React Context 还是简单地将它们作为道具传递更好?如果我应该使用 React Context,我该如何更正我的代码以使其正常工作?

【问题讨论】:

  • 第二种情况如何使用dataprovider
  • 我只会将它们作为道具传递 TBH。为什么在这里需要上下文?见Before You use context
  • @ShubhamKhatri 我已经更新了我的问题并添加了代码stackoverflow.com/posts/62057441/revisions
  • @RobinMétral 这是一个简化的示例。我的HeaderHeaderLinks,实际上需要使用location。所以我最终将相同的道具从一个组件传递到另一个组件。
  • @jupiteror 就个人而言,我仍然会使用道具(这是我对“使用 React Context 还是简单地将它们作为道具传递更好?”的看法)。你说的很简单,2-3 层的嵌套对于道具来说是很好的。上下文使您的实现更加复杂,除非您需要传递主题或复杂状态,否则我会保持简单。

标签: reactjs gatsby


【解决方案1】:

我最终使用来自@reach/routeruseLocation 来返回子组件中的位置。我只是将pageContext 作为道具传递给&lt;Breadcrumbs /&gt;,因为它只使用一次并且不会传递给任何子组件。

【讨论】:

    【解决方案2】:

    您可以使用wrapPageElement,而不是使用wrapRootElement 来使用ContexProvider,您可以在其中获取页面道具并将它们传递给DataProvider。这将确保每个页面上的 pageContext 和位置都发生变化

    export const wrapRootElement = ({ element }) => (
      <ThemeProvider theme={theme}>
          {element}
      </ThemeProvider>
    );
    
    export const wrapPageElement = ({ element, props }) => (
      <DataProvider value={props}>
          {element}
      </DataProvider>
    );
    

    export const DataContext = React.createContext();
    
    const DataProvider = ({ children, value }) => {
      const {location, pageContext} = value;
      return (
        <DataContext.Provider value={{
          location,
          pageContext
        }}>
          {children}
        </DataContext.Provider>
      )
    };
    
    export default DataContext
    export { DataProvider }
    

    【讨论】:

    • 这与盖茨比文档gatsbyjs.org/docs/browser-apis/#wrapRootElement 不矛盾吗?他们说:要设置 Provider 组件,请使用wrapRootElement
    • 同意,但您想要实现的内容需要仅在页面内而不是跨页面访问的上下文
    • 我最终使用来自@reach/router 的useLocation 来返回子组件中的位置。我只是将pageContext 作为道具传递给&lt;Breadcrumbs /&gt;,因为它只使用一次并且不会传递给任何子组件。
    • 但是上面的解决方案没有用。因为如果将来您需要在其他组件中使用它,您的解决方案并不完美
    • 因为说你想将 pageContext 传递给其他一些组件并且可能是一个深度嵌套的组件,所以你必须在每个级别传递这个 prop
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2020-05-28
    • 2011-10-13
    • 2020-02-04
    • 2019-07-25
    • 2018-11-20
    • 2020-03-23
    相关资源
    最近更新 更多