Footer组件中useEffect引发每4秒全页重渲染问题排查
问题现象
Footer组件中,useEffect每4秒触发一次全页及组件重渲染,预期仅更新轮播的项目元素。注释掉<CookieBanner />组件后该现象消失,且数据的控制台日志每4秒输出一次。
核心问题原因
- CookieBanner是异步客户端组件:在Next.js的
"use client"组件中,不能将组件定义为async函数。异步组件会返回Promise,React无法正确处理客户端组件的异步返回值,导致父组件(Footer)每次状态更新(比如currentProject变化)时,CookieBanner组件都会被重新初始化,进而触发不必要的全页重渲染。 - 内部组件重复创建:
ButtonComponent定义在CookieBanner组件内部,每次组件渲染都会重新创建这个子组件,间接导致重渲染优化失效。
解决方案
1. 移除CookieBanner的async关键字
当前CookieBanner代码中没有异步操作,完全不需要使用async,改为普通函数组件即可修复核心重渲染问题。
2. 提取内部组件到外部
将ButtonComponent移到CookieBanner组件外部,避免每次渲染重复创建组件,进一步优化重渲染性能。
修改后的CookieBanner代码
"use client" import Link from "next/link" import CookieConsent from "react-cookie-consent" type CookieBannerProps = { data?: CookieBanner } type CookieBannerButtonProps = { children: React.ReactNode onClick: () => void privacy_url?: string privacy_link_text?: string } // 提取到组件外部,避免每次渲染重新创建 const ButtonComponent = ({ children, onClick, privacy_url, privacy_link_text }: CookieBannerButtonProps) => { return ( <div className="flex items-center gap-5"> {privacy_url && ( <Link href={`/${privacy_url}`} className="flex items-center gap-2 text-sm text-white lg:text-base" > {privacy_link_text ? privacy_link_text : "Privacy Policy"} </Link> )} <button onClick={onClick} className="inline-flex items-center text-sm text-white lg:text-base" > <span className="pl-3">{children}</span> </button> </div> ) } export function CookieBanner({ data }: CookieBannerProps) { if (!data || !data.enabled) { return null } const { title, buttonText, privacy_link_text, privacy_url } = data const debug = process.env.NODE_ENV === "development" return ( <CookieConsent disableStyles location="bottom" buttonText={buttonText ? buttonText : "Accepteren"} cookieName="CookieConsent" expires={365} debug={debug} containerClasses="bg-black text-white justify-between flex flex-col sm:flex-row px-6 py-4 w-full sm:items-center fixed gap-3 bottom-0 left-0 w-full z-40" ButtonComponent={(props) => ( <ButtonComponent {...props} privacy_url={privacy_url} privacy_link_text={privacy_link_text} /> )} > <h3 className="text-lg sm:text-xl">{title}</h3> </CookieConsent> ) }
额外优化建议
- Footer中的
Socials组件也可以提取到组件外部,或者用React.memo包裹,避免每次Footer渲染重复创建组件。 - 确保
footerData保持为常量(当前代码已满足),避免每次渲染重新创建对象。
内容的提问来源于stack exchange,提问作者Galanthus
相关产品推荐
相关产品推荐

