在盖茨比中将Context Provider放在哪里?

时间:2019-09-23 13:17:28

标签: javascript reactjs axios gatsby react-context

我仅在第一次访问该网站时才需要运行某些功能(例如Office UI Fabric React的initializeIcons())和AXIOS调用(例如使用Context API检索登录用户)。在React Context中检索到的值,并使它可用于整个应用程序。

盖茨比将我页面的内容包装在布局中,例如:

const IndexPage = () =>
<Layout>
   Body of Index Page...
</Layout>
const AnotherPage = () =>    
<Layout>
   Body of Another Page...
</Layout>

布局如下:

const Layout = ({ children }) =>
<>
    <Header /> 
    <main>{children}</main>
    <Footer />
</>

我知道我可以在哪里放置上下文:

  • 页面周围(或者将在每次页面被点击时执行,并且其他页面也不可用):

    const IndexPage = () =>
    <MyContextProvider>
        <Layout>
           Context Available here
        </Layout>
    </MyContextProvider>
    
    const AnotherPage = () =>    
    <Layout>
        Context NOT available here
    </Layout>
    
  • 在版式中(或每次都会执行):

    const Layout = ({ children }) =>
    <MyContextProvider>
        <Header /> 
        <main>{children}</main>
        <Footer />
    </MyContextProvider>
    

我想我需要一个<app>根对象来包围我的上下文提供程序,但是用盖茨比实现这一目标的一种干净方法是什么?

我应该在哪里放置上下文提供程序?

2 个答案:

答案 0 :(得分:2)

您定义根目录布局。与常规布局相比,没有定义“可见”页面元素,而是在每个页面上需要隐藏的东西,例如ContextProviders,React Helmet,主题等:

RootLayout.jsx

export default function RootLayout({ children }) {
  return (
    <>
      <Helmet />
        <ThemeProvider theme={theme}>
          <CssBaseline />
          <ContextProvider>
            {children}
          </ContextProvider>
        </ThemeProvider>
    </>
  );
}

Gatsby通过gatsby-browser.jsgatsby-ssr.js隐式调用此根布局,并将其应用于您的每个页面。 Gatsby只需这两行相同的代码即可为您完成其余的工作。

gatsby-browser.js

export const wrapRootElement = ({ element }) => <RootLayout>{element}</RootLayout>;

gatsby-ssr.js

export const wrapRootElement = ({ element }) => <RootLayout>{element}</RootLayout>;

摘要:

  • 您将上下文提供者放在根目录中。

参考:

  • 我问了相关问题herehere。我在此答案中提供的代码是您和我的问题的解决方案。如果您的整个应用程序都需要此信息,那么它是一种很好的编码惯例,可以从React Redux等框架改编为使用Context Provider包装整个应用程序。
  • 提到了blog post @Lionel T。

答案 1 :(得分:0)

出于完整性考虑,盖茨比提供的API(通过gatsby-browser.js)仅运行一次函数

onClientEntry

export const onClientEntry = () => {
    console.log("Browser started!")
    // Put here run-only-once functions 
}

onInitialClientRender

export const onInitialClientRender = () => {
    console.log("First rendering completed!")
    // Put here run-only-once functions which need rendered output
}