<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miles Crighton</title>
    <description>The latest articles on DEV Community by Miles Crighton (@milescrighton).</description>
    <link>https://dev.to/milescrighton</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F84013%2F17fa750b-abe7-4033-b854-49b8314332f3.jpg</url>
      <title>DEV Community: Miles Crighton</title>
      <link>https://dev.to/milescrighton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/milescrighton"/>
    <language>en</language>
    <item>
      <title>Keeping persistent UI across routes with Gatsby's wrapPageElement</title>
      <dc:creator>Miles Crighton</dc:creator>
      <pubDate>Fri, 12 Mar 2021 16:57:40 +0000</pubDate>
      <link>https://dev.to/milescrighton/keeping-persistent-ui-across-routes-with-gatsby-s-wrappageelement-4o22</link>
      <guid>https://dev.to/milescrighton/keeping-persistent-ui-across-routes-with-gatsby-s-wrappageelement-4o22</guid>
      <description>&lt;p&gt;Nestled deep within Gatsby's docs, there's a couple of hella useful API functions: &lt;a href="https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/#wrapPageElement" rel="noopener noreferrer"&gt;&lt;code&gt;wrapPageElement&lt;/code&gt;&lt;/a&gt; and its big brother &lt;a href="https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/#wrapRootElement" rel="noopener noreferrer"&gt;&lt;code&gt;wrapRootElement&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These APIs give the opportunity to develop richer, complex UIs on top of Gatsby's static page generation.&lt;/p&gt;

&lt;p&gt;By exporting these functions we can let Gatsby know how it should wrap additional components around our pages, both at the app's root level and nested one deeper at the page level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70zm85o3byoayykau9y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70zm85o3byoayykau9y9.png" alt="wrapPageAPIs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This comes in use when persisting components across routes, essential to some of the below features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Media Player / Controls&lt;/li&gt;
&lt;li&gt;Navigation elements&lt;/li&gt;
&lt;li&gt;Sidebars &amp;amp; Menus&lt;/li&gt;
&lt;li&gt;App-level context providers (like &lt;code&gt;Redux&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In a rush? &lt;a href="https://github.com/miles-crighton/gatsby-persistent-ui" rel="noopener noreferrer"&gt;Check out the quick implementation&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What do you mean by persist?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Well, Gatsby's default behavior is to re-render all elements on a page whenever we change route.&lt;/p&gt;

&lt;p&gt;As described above we may need components to stay alive and mounted across routes or &lt;em&gt;persist&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this article we're going to focus on using &lt;code&gt;wrapPageElement&lt;/code&gt; to keep a layout component persistent across routes. There are multiple ways to do this, but I'm going to show you what I've found to be most elegant.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Assigning Layout Components&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What I'm calling a layout component can be any component that wraps around your page. A really basic example might include a header and a footer that sandwich your page's content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/Layout.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My awesome site!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Built with Gatsby.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sky's the limit with these layouts, anything that we want to keep alive across pages can be stuck into one. The only requirement is that it renders &lt;code&gt;{children}&lt;/code&gt; so the wrapped page is visible.&lt;/p&gt;

&lt;p&gt;We need to create a way of linking a layout component to a specific page component so that we can tell Gatsby how to correctly wrap it.&lt;/p&gt;

&lt;p&gt;This is pretty easy, we'll just assign a static &lt;code&gt;Layout&lt;/code&gt; property to our page component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/layout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;IndexPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;IndexPage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;Layout&lt;/code&gt; is uppercase just as a convention to indicate that we're working with a React component.&lt;/p&gt;

&lt;p&gt;That's all that's required for the page, now onto Gatsby config.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting up our Gatsby files&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now we need to tell Gatsby that we want it to wrap the page we've chosen with the assigned &lt;code&gt;Layout&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Within &lt;code&gt;gatsby-browser.js&lt;/code&gt; and &lt;code&gt;gatsby-ssr.js&lt;/code&gt; we can export &lt;code&gt;wrapPageElement&lt;/code&gt;. When Gatsby calls this function for each page it passes it two arguments; an element and some props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// gatsby-browser.js &amp;amp;&amp;amp; gatsby-ssr.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;wrapPageElement&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Fragment&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The element is simply the page component Gatsby wants to render, while the props is that page's props. These props include all kinds of useful data including any GraphQL queries made. (&lt;a href="https://www.gatsbyjs.com/docs/how-to/querying-data/page-query/" rel="noopener noreferrer"&gt;Check out more here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;We assign the &lt;code&gt;Layout&lt;/code&gt; variable using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator" rel="noopener noreferrer"&gt;nullish coalescing operator (??)&lt;/a&gt; which checks if there's a Layout property on our page component, if not it just returns a &lt;a href="https://reactjs.org/docs/fragments.html" rel="noopener noreferrer"&gt;React fragment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's important that we spread the page's props onto the &lt;code&gt;Layout&lt;/code&gt; so that any queries within the layout can be accessed via its own props.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In almost all cases you'll want to keep your &lt;code&gt;gatsby-ssr&lt;/code&gt; &amp;amp; &lt;code&gt;gatsby-browser&lt;/code&gt; config files the same so that your components can correctly be &lt;a href="https://www.gatsbyjs.com/docs/conceptual/react-hydration/" rel="noopener noreferrer"&gt;hydrated&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The result&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;That's it! If we assign the same &lt;code&gt;Layout&lt;/code&gt; to multiple pages and navigate between them Gatsby will make sure they're not re-rendered. This keeps any state within those layouts intact across routes.&lt;/p&gt;

&lt;p&gt;I've put together a repo containing a minimal example showing how a counter component keeps counting when routes change. Check it out if you want to dig deeper.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/miles-crighton/gatsby-persistent-ui" rel="noopener noreferrer"&gt;https://github.com/miles-crighton/gatsby-persistent-ui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's great about this method is it scales to how ever many layouts you want while being completely opt-in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekogh48udf6i3a4ejls5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekogh48udf6i3a4ejls5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't want a layout on a page, don't set a &lt;code&gt;Layout&lt;/code&gt; property - simple!&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>react</category>
      <category>intermediate</category>
    </item>
  </channel>
</rss>
