React自定义钩子执行过多触发Minified Error #185问题求助
问题描述
React组件Footer使用自定义钩子useLogoImageUrl时,钩子执行51次后抛出React压缩版错误#185,提示超出最大更新深度,这类错误通常由组件反复调用setState触发循环渲染导致。该组件是WP Block,仅在保存为Pattern时出现此错误。
涉及代码
Footer.js
import { useLogoImageUrl } from '../../../src/hooks/useLogoImageUrl'; const Item = ({ item }) => ( <div key={item.id}> <strong>{item.title}</strong> {item.children?.length > 0 && ( <ul> {item.children.map(subitem => ( <li key={subitem.id}> <a href={subitem.url}>{subitem.title}</a> </li> ))} </ul> )} </div> ); /** * Global Footer Component * * @param {Object} params * @param {string} params.logoImageUrl * @param {Array|null} params.menu * @param {string} params.instagramLink * @param {string} params.youtubeLink * ... * @param {string} params.sitemapLink * ... */ export const Footer = ({ menu = [], logoImageUrl, instagramLink, // ... sitemapLink, // ... }) => { const selectedLogoUrl = useLogoImageUrl(logoImageUrl); const currentYear = new Date().getFullYear(); const splitMenuData = menu?.reduce((acc, item, index) => { const chunkIndex = Math.floor(index / 2); if (!acc[chunkIndex]) { acc[chunkIndex] = []; } acc[chunkIndex].push(item); return acc; }, []); return ( <footer> <div> <div> <div> <a href="/" aria-label='logo'> <img src={selectedLogoUrl} alt="Logo" /> </a> <div> {/* Some hardcoded links */} </div> <div> {instagramLink && ( <a href={instagramLink} target="_blank" rel="noreferrer noopener"> <img src="/path/to/instagram.svg" alt="Instagram" /> </a> )} {/* ... */} </div> </div> <hr /> <nav> {splitMenuData?.map(row => row.map(item => ( <Item item={item} key={item.id} /> )) )} </nav> </div> <hr /> <div> <ul> {sitemapLink && ( <li> <a href={sitemapLink}>Sitemap</a> </li> )} {/* ... */} </ul> </div> </div> </footer> ); };
原自定义钩子useLogoImageUrl
import { DEFAULT_LOGO_IMAGE_DARK_SRC, DEFAULT_HERO_IMAGE_LIGHT_SRC, STYLE_MODE_DARK, } from '../constants'; export const useLogoImageUrl = ( path, styleMode ) => { const isDark = styleMode === STYLE_MODE_DARK; return ( path || ( isDark ? DEFAULT_HERO_IMAGE_LIGHT_SRC : DEFAULT_LOGO_IMAGE_DARK_SRC ) ); };
修改后的自定义钩子(尝试useMemo后)
import { useMemo } from '@wordpress/element'; import { DEFAULT_LOGO_IMAGE_DARK_SRC, DEFAULT_HERO_IMAGE_LIGHT_SRC, STYLE_MODE_DARK, } from '../constants'; export const useLogoImageUrl = ( path, styleMode ) => { console.log( styleMode ); const isDark = 'dark' === STYLE_MODE_DARK; return useMemo( () => { return ( path || ( isDark ? DEFAULT_HERO_IMAGE_LIGHT_SRC : DEFAULT_LOGO_IMAGE_DARK_SRC ) ); }, [ path, isDark ] ); };
已尝试的无效方案
- 在组件和自定义钩子中使用
useMemo() - 注释掉
Item组件
问题排查与修复
1. 修复自定义钩子的逻辑错误
修改后的钩子存在硬编码错误,导致isDark值固定无法动态切换:
// 错误写法:将常量与字符串直接比较,isDark成为固定值 const isDark = 'dark' === STYLE_MODE_DARK; // 正确写法:使用传入的styleMode参数判断主题模式 const isDark = styleMode === STYLE_MODE_DARK;
2. 补全钩子调用的缺失参数
Footer组件调用useLogoImageUrl时仅传入了logoImageUrl,缺少styleMode参数,导致钩子中styleMode为undefined。需补全参数(示例以WP的主题模式获取逻辑为例,根据实际场景调整):
// 先获取当前主题模式,示例从WP设置中获取 const styleMode = useSetting('appearance/styleMode'); // 补全钩子调用参数 const selectedLogoUrl = useLogoImageUrl(logoImageUrl, styleMode);
3. 稳定化组件内计算逻辑
splitMenuData每次渲染都会生成新数组,触发子组件不必要重渲染,用useMemo包裹稳定化:
const splitMenuData = useMemo(() => { return menu?.reduce((acc, item, index) => { const chunkIndex = Math.floor(index / 2); if (!acc[chunkIndex]) { acc[chunkIndex] = []; } acc[chunkIndex].push(item); return acc; }, []); }, [menu]);
4. 排查WP Block保存逻辑
由于错误仅在保存为Pattern时出现,需确认:
- Block的
save函数是否正确序列化组件输出,避免保存流程触发循环渲染 logoImageUrl等属性在保存时是否被动态修改,导致每次渲染生成新值,触发钩子与组件反复更新
内容的提问来源于stack exchange,提问作者Nik Tojo
相关产品推荐
相关产品推荐

