Search code examples
javascriptreactjsgraphqlgatsbystyled-components

How to use page query while using root-wrapper for providing Theme with Gatsby


I am using wrapRootElement function in gatsby for providing ThemeProvider of styled-component on the root element. Here is the code :

export const wrapRootElement = () => {
  if (typeof window === 'undefined') return <span>Something went wrong!</span>
  return(
      <ThemeProvider theme={theme}>
         <FadeTransitionRouter>
            <Page path="/" page={<IndexPage />} />
            <Page path="/plan" page={<PlanPage />} />
            <Page path="/promos/:slug" page={<Template />} />
        </FadeTransitionRouter>
      </ThemeProvider>
)};

Because of this I am compelled to use staticQuery in pages as page queries are not working there. But I need to use page queries to introduce variables in graphql queries. How can I achieve this ? If I do not use wrapRootElement, my page queries works fine. But it is important for me to use it as I need to provide my external Theme to all the pages.

Thanks in advance.


Solution

  • You aren't wrapping the root element here, you're replacing the entirety of the Gatsby app tree. You're probably seeing warnings about page queries being ignored because they're in files that aren't being treated like pages, which is likely where the source of confusion is.

    Here's the example the Gatsby docs provide:

    exports.wrapRootElement = ({ element }) => {
      return (
        <Provider store={store}>
          {element}
        </Provider>
      )
    }
    

    Note how this example accepts an element prop that it passes down as the children to the Provider component? That's what you're missing. You probably want something like this:

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

    You don't need to check for the existence of window here. If you're in gatsby-browser.js it will only ever be executed in the context of the browser. If you're in gatsby-ssr.js it'll only ever be executed in the context of node. Either way, they need to produce the same DOM output in order to have React hydrate cleanly. Bailing in the way you've shown will result in your entire DOM being replaced when React hydrates, which is less efficient than a client-side rendered app.

    Finally, I removed the FadeTransitionRouter bit because you haven't shared what that is and it is unlikely to be compatible with Gatsby routing. If you'd like to have page transitions, this page in the documentation has details on how to set this up.