我一直在尝试诊断为什么我在useEffect
单击一个组件时多次运行<Link>
,即使依赖项为空。我找到了一个很好的方法来找出我的问题所在,使用这个答案中的解决方案。
本质上,我添加了一个useEffect
记录console
组件重新渲染的日志,然后我一直向上爬到树上,直到找到不重新渲染的最高级别组件。
useEffect(()=>{
console.log('this component is rendered');
},[]);
我正在使用gatsby-plugin-layout,我AppLayout
的组件是不会发生重新渲染的组件,这意味着问题出在我的页面模板中,如gatsby-source-prismic-graphql中定义的那样,这是下一个单击console
时记录页面更改的树下的东西<Link>
。综上所述,我不完全确定这里的问题出在哪里,或者我的内心是否有什么东西AppLayout
正在gatsby-config.js
抛弃它并导致这种行为发生。我该如何解决它,这样我的页面就不会不断地重新渲染?下面包括我的AppLayout
和gatsby-config.js
。
提前致谢。
盖茨比-config.js
/* 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: (() => ['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'),
},
},
],
};
应用布局.tsx
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) => {
const [fadeEffectVisible, setFadeEffectVisible] = useState(false);
const [page, setPage] = useState(pathname);
const prevPage = usePrevious(pathname);
useEffect(
() => () => {
if (pathname !== prevPage) {
setFadeEffectVisible(true);
setPage(page);
}
},
[pathname],
);
const handleFadeEffectEntered = () => {
setTimeout(() => {
setFadeEffectVisible(false);
}, 50);
};
return (
<StaticQuery
query={`${NavQuery}`}
render={(data) => (
<>
<AppContext>
<CSSTransition
in={fadeEffectVisible}
timeout={timeout}
classNames={{
enter: s.fadeEffectEnter,
enterActive: s.fadeEffectEnterActive,
enterDone: s.fadeEffectEnterDone,
exit: s.fadeEffectExit,
exitActive: s.fadeEffectExitActive,
}}
onEntered={handleFadeEffectEntered}
>
<div className={s.fadeEffect} aria-hidden="true" />
</CSSTransition>
<NavigationSkipLink />
<Header navigationContent={data.prismic.allNavigations.edges[0].node} />
<TransitionGroup component={null}>
<CSSTransition
key={pathname}
timeout={timeout}
classNames={{
enter: s.pageEnter,
}}
>
<div id={MainContentId} className={s.layout}>
{children}
<Footer navigationItems={data.prismic.allNavigations.edges[0].node} />
{isDev && <Devtools />}
</div>
</CSSTransition>
</TransitionGroup>
</AppContext>
</>
)}
/>
);
};