Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put Context Provider in Gatsby?

I need to run some functions (eg. Office UI Fabric React's initializeIcons()) and AXIOS call (eg. retrieve the logged-in user with Context API) only the first time the site is hit, then store the retrieved values in the React Context and make it available to the whole application.

Gatsby is wrapping my pages' content in a Layout, like:

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

with Layout being like:

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

I know where I can NOT put my Context:

  • around the pages (or it will be executed everytime the page is hit, and also not available to the other pages):

    const IndexPage = () =>
    <MyContextProvider>
        <Layout>
           Context Available here
        </Layout>
    </MyContextProvider>
    
    const AnotherPage = () =>    
    <Layout>
        Context NOT available here
    </Layout>
    
  • in the Layout (or it will be executed every time):

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

I suppose I need a root <app> object to surround with my Context Provider, but what's a clean way to achieve that with Gatsby?

Where should I put my Context Provider?

like image 621
Andrea Ligios Avatar asked Sep 23 '19 13:09

Andrea Ligios


People also ask

Is context provider a component?

Context.ProviderEvery Context object comes with a Provider React component that allows consuming components to subscribe to context changes. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers.

Should I use props or context?

If you are using props, and you have to pass data to the last Child component amongst multiple Nested Component. The data needs to be passed through every component in the tree using props. So every component needs to know about that props data even if it's not using it. Context Solves this problem.

How do you use redux in The Great Gatsby?

In order to use Redux for custom state management in a Gatsby site, you'll need to hook into two of Gatsby's extension points: Wrap the root element in your Gatsby markup once using wrapRootElement , an API supporting both Gatsby's server rendering and browser JavaScript processes.


1 Answers

You define a root layout. In contrast to the normal layout there are no "visible" page elements defined but hidden stuff you need on every page like ContextProviders, React Helmet, themes, etc:

RootLayout.jsx:

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

Gatsby calls this root layout implicitly via gatsby-browser.js and gatsby-ssr.js and applies it to each of your pages. Those two identical lines of code are all you need for Gatsby to handle the rest for you.

gatsby-browser.js:

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

gatsby-ssr.js:

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

Summary:

  • You put your Context Provider in a root layout.

References:

  • I asked related questions here and here. The code I provided in this answer is the solution to your and my question. It is good coding practice adapted from frameworks such as React Redux to wrap your whole app with the Context Provider if your whole app needs this information.
  • The blog post @Lionel T mentioned.
like image 121
EliteRaceElephant Avatar answered Oct 12 '22 23:10

EliteRaceElephant