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

Next.js主题切换器报错求助:No router instance found问题解决

问题解决:Next.js主题切换器报错"No router instance found"

这个错误的核心原因是你在服务端渲染/静态生成的组件中直接调用了next/router的相关方法——next/router的实例只存在于客户端,服务端环境下没有router对象,所以会抛出这个错误。

下面是具体的解决思路和代码示例:

方案1:避免不必要的router使用(推荐)

主题切换大多不需要依赖路由跳转,直接用状态管理结合localStorage保存用户偏好即可,完全绕开router的问题:

// 如果你用的是Next.js 13+ App Router,必须加'use client'声明这是客户端组件
'use client';

import { useState, useEffect } from 'react';

export default function ThemeToggleButton() {
  const [currentTheme, setCurrentTheme] = useState('light');

  // 组件挂载时读取本地存储的主题
  useEffect(() => {
    const savedTheme = localStorage.getItem('app-theme') || 'light';
    setCurrentTheme(savedTheme);
    // 给根元素添加主题类,配合CSS变量实现主题切换
    document.documentElement.classList.toggle('dark-theme', savedTheme === 'dark');
  }, []);

  const handleThemeToggle = () => {
    const newTheme = currentTheme === 'light' ? 'dark' : 'light';
    setCurrentTheme(newTheme);
    localStorage.setItem('app-theme', newTheme);
    document.documentElement.classList.toggle('dark-theme', newTheme === 'dark');
  };

  return (
    <button onClick={handleThemeToggle}>
      切换到{currentTheme === 'light' ? '深色' : '浅色'}主题
    </button>
  );
}

方案2:如果必须使用router(比如路由携带主题参数)

确保router的相关操作只在客户端环境执行:

Pages Router 场景

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

export default function ThemeToggle() {
  const router = useRouter();

  const toggleTheme = () => {
    // 先判断是否在客户端环境
    if (typeof window !== 'undefined') {
      const targetTheme = router.query.theme === 'dark' ? 'light' : 'dark';
      router.push({
        pathname: router.pathname,
        query: { ...router.query, theme: targetTheme }
      });
    }
  };

  // 初始化主题时也要确保在客户端执行
  useEffect(() => {
    if (typeof window !== 'undefined') {
      const currentTheme = router.query.theme || 'light';
      document.documentElement.classList.toggle('dark-theme', currentTheme === 'dark');
    }
  }, [router.query.theme]);

  return <button onClick={toggleTheme}>切换主题</button>;
}

App Router 场景(Next.js 13+)

'use client';

import { useRouter, useSearchParams } from 'next/navigation';
import { useState, useEffect } from 'react';

export default function ThemeToggle() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [currentTheme, setCurrentTheme] = useState('light');

  useEffect(() => {
    const themeFromUrl = searchParams.get('theme') || 'light';
    setCurrentTheme(themeFromUrl);
    document.documentElement.classList.toggle('dark-theme', themeFromUrl === 'dark');
  }, [searchParams]);

  const toggleTheme = () => {
    const newTheme = currentTheme === 'light' ? 'dark' : 'light';
    const newSearchParams = new URLSearchParams(searchParams);
    newSearchParams.set('theme', newTheme);
    router.push(`?${newSearchParams.toString()}`);
  };

  return <button onClick={toggleTheme}>切换主题</button>;
}

关键注意点

  • Next.js 13+ App Router中,所有使用客户端API(比如useRouter、window对象)的组件必须添加'use client'指令,标记为客户端组件。
  • 任何涉及window或router的操作,都要确保只在客户端执行——要么用typeof window !== 'undefined'判断,要么放在useEffect(组件挂载后执行,此时已在客户端)里。

内容的提问来源于stack exchange,提问作者YACIN EL KAMALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:35:18