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

NextJS中能否在_document.js中使用React Hooks?

能否在自定义_document.js中使用React Hooks?

结论:不能直接在_document.js中使用React Hooks(包括useRouter)

原因分析

  1. 组件类型限制:_document.js是Next.js中负责渲染HTML骨架的特殊文件,它必须继承自Next.js提供的Document类组件。而React Hooks的核心规则之一是只能在函数组件或自定义Hooks中调用,类组件内无法使用Hooks,这直接触发了"breaking rules of hooks"错误。
  2. 运行环境与依赖冲突:useRouter是客户端路由钩子,依赖浏览器端的路由状态初始化。但_document.js仅在服务器端首次渲染页面时执行,此时客户端路由环境尚未构建,即便强行调用也无法获取有效路由信息,同时违反Hooks的调用规则。

可行替代方案

方案1:在_app.js中处理客户端动态更新

将地区类名的逻辑迁移到自定义_app.js中,这里是标准的函数组件,可安全使用useRouter,并通过useEffect在客户端渲染时同步body类名:

import { useEffect } from 'react';
import { useRouter } from 'next/router';
import App from 'next/app';

function MyApp({ Component, pageProps }) {
  const router = useRouter();
  const { locale } = router;

  useEffect(() => {
    // 清除旧的地区类名
    document.body.classList.forEach(cls => {
      if (cls.startsWith('locale-')) document.body.classList.remove(cls);
    });
    // 添加当前地区类名
    document.body.classList.add(`locale-${locale}`);
  }, [locale]);

  return <Component {...pageProps} />;
}

export default MyApp;

该方案会在客户端路由切换(包括locale变更)时自动更新body类名,完美适配Tailwind主题的动态切换需求。

方案2:服务器端渲染时注入类名

如果需要在服务器端生成HTML时就添加类名(适用于SEO或首次渲染即适配主题的场景),可在_document.js的getInitialProps中获取locale,再传递给render方法:

import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    // 从ctx中直接获取Next.js提供的locale
    const { locale } = ctx;
    return { ...initialProps, locale };
  }

  render() {
    return (
      <Html>
        <Head />
        <body className={`locale-${this.props.locale}`}>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

注意:该方案仅处理服务器端首次渲染的类名,若客户端切换locale,需结合_app.js的逻辑同步更新body类名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:54:29