React使用ApiContext搭配ThemeProvider切换主题时状态不更新如何解决
问题根因
- ThemeProvider 没有维护React响应式状态,反而直接调用
useThemeContext消费自身需要提供的Context值,仅能拿到初始化的静态默认值,没有状态更新能力。 - 初始定义的
toggleTurn方法仅对静态对象的属性做取反返回,没有调用React状态更新API,无法触发组件重渲染,状态不会持久变更。 - Template中调用
toggleTurn后立即打印theme,React状态更新是异步批量执行的,此时拿到的是当前渲染周期的旧值,不是更新后的状态。
修复方案
仅需要修改ThemeProvider和Template.tsx两个文件即可:
1. 重写ThemeProvider
import React, { FC, ReactNode, useState } from 'react'; import ThemeContext from "../context/themeContext"; export const ThemeProvider: FC<{children: ReactNode}> = ({ children}) => { // 内部维护响应式主题状态 const [theme, setTheme] = useState<boolean>(false); // 实现主题切换方法,触发状态更新和重渲染 const toggleTurn = () => setTheme(prev => !prev); return ( <ThemeContext.Provider value={{ theme, toggleTurn }}> {children} </ThemeContext.Provider> ) } export default ThemeProvider;
2. 调整Template的状态打印逻辑
如果需要查看最新的主题状态,通过useEffect监听theme变化后打印即可:
import React, { FC, ReactElement, MouseEvent, useEffect } from 'react'; import { useThemeContext } from '../context/themeContext'; const Template: FC = (): ReactElement<any, any> | null => { const { theme, toggleTurn } = useThemeContext(); // 监听theme变更,打印最新状态 useEffect(() => { console.log(theme); }, [theme]) const toggleTheme = (e: MouseEvent<HTMLButtonElement>) => { e.preventDefault(); toggleTurn?.(); }; return ( <button type="button" onClick={toggleTheme}> 切换主题 </button> ) };
剩下的IthemeContext.ts、themeContext.ts、App.tsx无需修改。
内容的提问来源于stack exchange,提问作者Reuno
相关产品推荐
相关产品推荐

