You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键说明

  1. 状态驱动重渲染:用currentAnchor状态跟踪锚点变化,状态更新时组件自动重渲染,避免在事件回调中调用Hook。
  2. 双事件监听:同时监听popstate和hashchange,覆盖浏览器前进后退、直接修改锚点等所有场景。
  3. Hook正确使用:useTranslation在组件顶层调用,确保符合React Hook规则,翻译文本可正常获取。

内容的提问来源于stack exchange,提问作者chraebsli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 07:37:18