window.location变化时如何重渲染React组件?解决react-helmet及i18next报错
解决锚点变化时React组件重渲染更新标题及Hook调用错误问题
问题原因
你遇到的Invalid hook call错误,是因为在popstate事件的回调函数内部调用了React Hook(比如useTranslation)——React Hook只能在函数组件的顶层作用域调用,不能嵌套在事件回调、循环或条件判断中。
解决方案
通过状态跟踪锚点变化触发组件重渲染,在组件顶层正常使用Hook获取翻译文本,再通过react-helmet更新标题。以下是完整实现:
import { useEffect, useState } from 'react'; import { Helmet } from 'react-helmet'; import { useTranslation } from 'react-i18next'; const PageTitle = () => { const { t } = useTranslation(); // 初始化状态为当前锚点 const [currentAnchor, setCurrentAnchor] = useState(window.location.hash); useEffect(() => { const handleAnchorChange = () => { // 更新状态触发组件重渲染,不在此回调内调用Hook setCurrentAnchor(window.location.hash); }; // 同时监听popstate(浏览器前进后退)和hashchange(锚点直接修改)事件 window.addEventListener('popstate', handleAnchorChange); window.addEventListener('hashchange', handleAnchorChange); // 组件卸载时清理监听 return () => { window.removeEventListener('popstate', handleAnchorChange); window.removeEventListener('hashchange', handleAnchorChange); }; }, []); // 根据当前锚点匹配对应翻译标题 const getTitle = () => { switch (currentAnchor) { case '#profile': return t('pageTitles.profile'); case '#settings': return t('pageTitles.settings'); case '#dashboard': return t('pageTitles.dashboard'); default: return t('pageTitles.home'); } }; return ( <Helmet> <title>{getTitle()}</title> </Helmet> ); }; export default PageTitle;
关键说明
- 状态驱动重渲染:用
currentAnchor状态跟踪锚点变化,状态更新时组件自动重渲染,避免在事件回调中调用Hook。 - 双事件监听:同时监听
popstate和hashchange,覆盖浏览器前进后退、直接修改锚点等所有场景。 - Hook正确使用:
useTranslation在组件顶层调用,确保符合React Hook规则,翻译文本可正常获取。
内容的提问来源于stack exchange,提问作者chraebsli
相关产品推荐
相关产品推荐

