React项目从RTK迁移到Rematch时主题切换触发Invalid Hook call错误
错误原因
核心问题是违反了React Hook的使用规则:所有Hook必须在React函数组件的顶层作用域调用,不能在普通回调函数、嵌套函数、条件分支、循环语句中调用。
你定义的DispatchThemes是传递给ThemeSwitcher的事件回调函数,只有用户切换主题开关时才会触发执行,此时函数执行上下文不属于组件渲染的顶层流程,因此函数内部调用的useDispatch和useEffect两个Hook都不符合调用规则,直接触发Invalid hook call报错。
修复方案
完全不需要在回调函数中调用Hook,按如下步骤修改Navigation组件即可:
- 在Navigation组件的顶层(和其他Hook同层级)调用
useDispatch拿到全局dispatch实例 - 把
DispatchThemes改写为无Hook的普通事件处理函数,内部直接调用dispatch方法更新store - 将改写后的处理函数传递给
ThemeSwitcher的themeChanger属性
修复后的Navigation组件核心代码示例
const Navigation: React.FC = () => { // 其他原有代码保持不变 // 1. 组件顶层调用useDispatch,符合Hook规则 const dispatch = useDispatch<Dispatch>() // Get OS-level preference for dark mode const prefersDarkMode: boolean | undefined = useMediaQuery("(prefers-color-scheme: dark)"); // 2. 改写为普通事件处理函数,无任何Hook调用 const changeTheme = (themeMode: boolean | undefined) => { dispatch.themeModel.setDarkModeAsync(themeMode); } return ( {/* 其他原有代码保持不变 */} {/* 3. 传递改写后的处理函数 */} <ThemeSwitcher useOs={false} themeChanger={changeTheme} /> {/* 其他原有代码保持不变 */} ); }
你原来的代码中额外加的useEffect属于冗余逻辑,你的需求是用户切换开关时立即触发store更新,不需要等待副作用执行,直接调用dispatch即可。
内容的提问来源于stack exchange,提问作者Simon Mayrhofer
相关产品推荐
相关产品推荐

