title: Page Templates re-rendering on every click in Prismic & Gatsby
body: <p>I've been trying to diagnose why I've got <code>useEffect</code> running multiple times when I click a <code>&lt;Link&gt;</code> component, even with empty dependencies. I found a good way to figure out where my problem lies, using the solution in <a href="https://stackoverflow.com/questions/60618844/react-hooks-useeffect-is-called-twice-even-if-an-empty-array-is-used-as-an-ar/60619061#60619061">this answer.</a></p>
  <p>Essentially I'm adding a <code>useEffect</code> that <code>console</code> logs components went they re-render, and I went all the way up the tree till I found the highest level component that doesn't re-render.</p>
  <pre><code>useEffect(()=&gt;{
    console.log('this component is rendered');
  },[]);
  </code></pre>
  <p>I'm using <a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-layout/" rel="nofollow noreferrer">gatsby-plugin-layout</a>, and my <code>AppLayout</code> component is the component where the re-render does not occur, meaning that the problem lies within my page templates, as defined in <a href="https://www.gatsbyjs.com/plugins/gatsby-source-prismic-graphql/" rel="nofollow noreferrer">gatsby-source-prismic-graphql</a>, which are the next things down the tree where the <code>console</code> logs the page change when the <code>&lt;Link&gt;</code> is clicked. All this to say, I'm not entirely sure where the problem here lies, or if there is something within my <code>AppLayout</code> or <code>gatsby-config.js</code> that is throwing it off and making this behavior occur. How can I fix it so my pages aren't constantly re-rendering? Included below are my <code>AppLayout</code> and <code>gatsby-config.js</code>.</p>
  <p>Thanks in advance.</p>
  <p><strong>gatsby-config.js</strong></p>
  <pre><code>/* eslint-disable @typescript-eslint/camelcase */
  const path = require('path');
  
  require('dotenv').config({
    path: `.env.${process.env.NODE_ENV}`,
  });
  
  const site = require('./config/site');
  
  const pathPrefix = site.pathPrefix === '/' ? '' : site.pathPrefix;
  
  module.exports = {
    pathPrefix: site.pathPrefix,
    siteMetadata: {
      siteUrl: site.url + pathPrefix,
      pathPrefix,
      title: site.title,
      titleAlt: site.titleAlt,
      titleTemplate: site.titleTemplate,
      description: site.description,
      banner: site.logo,
      headline: site.headline,
      siteLanguage: site.siteLanguage,
      ogLanguage: site.ogLanguage,
      author: site.author,
      twitter: site.twitter,
      facebook: site.facebook,
    },
    plugins: [
      'gatsby-plugin-react-helmet-async',
      'gatsby-plugin-typescript',
      'gatsby-plugin-sharp',
      'gatsby-plugin-sitemap',
      'gatsby-transformer-sharp',
      {
        resolve: 'gatsby-source-filesystem',
        options: {
          name: 'images',
          path: path.join(__dirname, `src`, `assets`, `images`),
        },
      },
      {
        resolve: 'gatsby-plugin-manifest',
        options: {
          name: 'one-day-doors-and-closets',
          short_name: 'starter',
          start_url: '/',
          background_color: '#663399',
          theme_color: '#663399',
          display: 'minimal-ui',
          icon: 'src/assets/images/icon.png',
        },
      },
      {
        resolve: '@sentry/gatsby',
        options: {
          dsn: process.env.SENTRY_DSN,
          enabled: (() =&gt; ['production'].indexOf(process.env.NODE_ENV) !== -1)(),
        },
      },
      {
        resolve: 'gatsby-plugin-react-svg',
        options: {
          rule: {
            include: path.resolve(__dirname, 'src/assets/svg'),
          },
        },
      },
      {
        resolve: 'gatsby-source-prismic-graphql',
        options: {
          repositoryName: `${process.env.PRISMIC_REPOSITORY_NAME}`,
          defaultLang: 'en-us',
          path: '/preview',
          previews: false,
          accessToken: `${process.env.PRISMIC_ACCESS_TOKEN}`,
          pages: [
            {
              type: 'Homepage',
              match: '/',
              component: require.resolve('./src/pages/index.tsx'),
            },
            {
              type: 'Landing',
              match: '/:uid',
              component: require.resolve('./src/templates/landing.tsx'),
            },
            {
              type: 'Legal',
              match: '/:uid',
              component: require.resolve('./src/templates/legal.tsx'),
            },
            {
              type: 'Locator',
              match: '/:uid',
              component: require.resolve('./src/pages/locations.tsx'),
            },
            {
              type: 'Product',
              match: '/products/:uid',
              component: require.resolve('./src/templates/product.tsx'),
            },
          ],
        },
      },
      {
        resolve: 'gatsby-plugin-layout',
        options: {
          component: require.resolve('./src/components/app-layout/AppLayout.tsx'),
        },
      },
    ],
  };
  </code></pre>
  <p><strong>AppLayout.tsx</strong></p>
  <pre><code>import React, { ReactNode, useEffect, useState } from 'react';
  
  import { Devtools } from 'components/devtools/Devtools';
  import { Footer } from 'components/footer/Footer';
  import { Header } from 'components/header/Header';
  import { NavigationSkipLink } from 'components/navigation-skip-link/NavigationSkipLink';
  import { AppContext } from 'contexts/app-context/AppContext';
  import { graphql, StaticQuery } from 'gatsby';
  import { usePrevious } from 'hooks/use-previous';
  import { TransitionGroup, CSSTransition } from 'react-transition-group';
  
  import s from './AppLayout.scss';
  
  interface AppLayoutProps {
    props: any;
    children: ReactNode;
    location: any;
  }
  
  const isDev = process.env.NODE_ENV === 'development';
  
  export const MainContentId = 'maincontent';
  export const timeout = 250;
  
  const NavQuery = graphql`
    query NavQuery {
      prismic {
        allNavigations {
          edges {
            node {
              ...NotificationBar
              ...NavigationItems
              ...FooterNavigationItems
              ...LegalNavigationItems
            }
          }
        }
      }
    }
  `;
  
  // eslint-disable-next-line react/display-name
  export default ({ children, location: { pathname } }: AppLayoutProps) =&gt; {
    const [fadeEffectVisible, setFadeEffectVisible] = useState(false);
    const [page, setPage] = useState(pathname);
    const prevPage = usePrevious(pathname);
  
    useEffect(
      () =&gt; () =&gt; {
        if (pathname !== prevPage) {
          setFadeEffectVisible(true);
          setPage(page);
        }
      },
      [pathname],
    );
  
    const handleFadeEffectEntered = () =&gt; {
      setTimeout(() =&gt; {
        setFadeEffectVisible(false);
      }, 50);
    };
  
    return (
      &lt;StaticQuery
        query={`${NavQuery}`}
        render={(data) =&gt; (
          &lt;&gt;
            &lt;AppContext&gt;
              &lt;CSSTransition
                in={fadeEffectVisible}
                timeout={timeout}
                classNames={{
                  enter: s.fadeEffectEnter,
                  enterActive: s.fadeEffectEnterActive,
                  enterDone: s.fadeEffectEnterDone,
                  exit: s.fadeEffectExit,
                  exitActive: s.fadeEffectExitActive,
                }}
                onEntered={handleFadeEffectEntered}
              &gt;
                &lt;div className={s.fadeEffect} aria-hidden=&quot;true&quot; /&gt;
              &lt;/CSSTransition&gt;
  
              &lt;NavigationSkipLink /&gt;
              &lt;Header navigationContent={data.prismic.allNavigations.edges[0].node} /&gt;
              &lt;TransitionGroup component={null}&gt;
                &lt;CSSTransition
                  key={pathname}
                  timeout={timeout}
                  classNames={{
                    enter: s.pageEnter,
                  }}
                &gt;
                  &lt;div id={MainContentId} className={s.layout}&gt;
                    {children}
  
                    &lt;Footer navigationItems={data.prismic.allNavigations.edges[0].node} /&gt;
  
                    {isDev &amp;&amp; &lt;Devtools /&gt;}
                  &lt;/div&gt;
                &lt;/CSSTransition&gt;
              &lt;/TransitionGroup&gt;
            &lt;/AppContext&gt;
          &lt;/&gt;
        )}
      /&gt;
    );
  };
  </code></pre>