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

Next.js + TypeScript中使用useContext实现MUI双主题时遇useThemeContext不是函数的错误求助

Next.js + TypeScript中使用useContext实现MUI双主题时遇useThemeContext不是函数的错误求助

我来帮你排查这个问题!你遇到的TypeError: useThemeContext is not a function错误,大概率是Theme Context的导出/导入环节出了问题,或者Context本身的定义不符合规范。结合你给出的代码片段,我一步步帮你梳理:

首先,确认Theme Context的定义是否符合规范

你提到在@/providers/theme_context_provider里实现了Context,但没贴出代码,这很可能是问题根源。一个标准的useContext实现需要包含三个核心部分,给你一个可参考的正确实现:

// @/providers/ThemeContextProvider.tsx
'use client';

import { createContext, useContext, useState, ReactNode } from 'react';
import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
import { lightTheme, darkTheme } from '@/theme';

// 先定义Context的类型,确保类型安全
type ThemeContextType = {
  isDarkMode: boolean;
  toggleTheme: () => void;
};

// 创建Context,初始值可以设为null,但要在自定义钩子中做校验
const ThemeContext = createContext<ThemeContextType | null>(null);

// 封装自定义钩子,避免重复编写useContext和校验逻辑
export const useThemeContext = () => {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useThemeContext必须在ThemeContextProvider内部使用');
  }
  return context;
};

// 实现Provider组件,管理主题状态并包裹MUI的ThemeProvider
export const ThemeContextProvider = ({ children }: { children: ReactNode }) => {
  // 初始化主题,可从localStorage读取或跟随系统偏好
  const [isDarkMode, setIsDarkMode] = useState(false);

  const toggleTheme = () => {
    setIsDarkMode(prev => !prev);
    // 可选:将主题偏好保存到localStorage,刷新后保持状态
    localStorage.setItem('theme', isDarkMode ? 'light' : 'dark');
  };

  const currentTheme = isDarkMode ? darkTheme : lightTheme;

  return (
    <ThemeContext.Provider value={{ isDarkMode, toggleTheme }}>
      <MuiThemeProvider theme={currentTheme}>
        {children}
      </MuiThemeProvider>
    </ThemeContext.Provider>
  );
};

然后检查导入与使用是否正确

  1. 导入名称匹配:你在page.tsx中的导入如果是import { useThemeContext } from '@/providers/theme_context_provider';,要确保Provider文件里确实是命名导出了useThemeContext,而不是默认导出(如果是默认导出,导入时不能用花括号包裹)。
  2. 组件树包裹:必须确保你的page.tsx(或整个App)被ThemeContextProvider包裹。比如在layout.tsx中这样配置:
// src/app/layout.tsx
import { ThemeContextProvider } from '@/providers/ThemeContextProvider';
import { Roboto } from 'next/font/google';

const roboto = Roboto({
  weight: ['300', '400', '500', '700'],
  subsets: ['latin'],
  variable: '--font-roboto',
});

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={roboto.variable}>
        <ThemeContextProvider>
          {children}
        </ThemeContextProvider>
      </body>
    </html>
  );
}

最后排查细节问题

  • 文件名大小写:TypeScript对文件名大小写敏感,确保导入路径的文件名和实际文件名完全匹配
  • 客户端指令:在App Router中,所有涉及客户端交互的组件(包括Context Provider和使用useThemeContext的组件)都要加上'use client';指令
  • 导出方式:如果你的useThemeContext是默认导出,导入时要写成import useThemeContext from '@/providers/theme_context_provider';

按照上面的步骤排查,应该能解决useThemeContext is not a function的问题。如果还有问题,可以把你的theme_context_provider代码贴出来,我再帮你细化排查!

备注:内容来源于stack exchange,提问作者Muhammad Sharjeel Maqsood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 12:48:08