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> ); };
然后检查导入与使用是否正确
- 导入名称匹配:你在
page.tsx中的导入如果是import { useThemeContext } from '@/providers/theme_context_provider';,要确保Provider文件里确实是命名导出了useThemeContext,而不是默认导出(如果是默认导出,导入时不能用花括号包裹)。 - 组件树包裹:必须确保你的
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
相关产品推荐
相关产品推荐

