Reputation: 50203
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?
Upvotes: 12
Views: 3763
Reputation: 50203
For completeness, the APIs Gatsby provides (through gatsby-browser.js
) to run a function only once are:
export const onClientEntry = () => {
console.log("Browser started!")
// Put here run-only-once functions
}
export const onInitialClientRender = () => {
console.log("First rendering completed!")
// Put here run-only-once functions which need rendered output
}
Upvotes: 0
Reputation: 8162
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:
References:
Upvotes: 11