rematchjs 上的 Hook 调用无效
Posted
技术标签:
【中文标题】rematchjs 上的 Hook 调用无效【英文标题】:Invalid Hook call on rematchjs 【发布时间】:2022-01-06 15:33:38 【问题描述】:我将有一个reactjs
网站,我想在该网站上从“rtk”迁移到“rematch”。
在我的 Navigation 中,我将有一个主题切换器,它在 rematch
商店上执行调度。但我总是得到错误:
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:
-
您的 React 和渲染器版本可能不匹配(例如 React DOM)
您可能违反了 Hooks 规则
您可能在同一个应用程序中拥有多个 React 副本
有关如何调试和修复此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。
这是我的导航
import React, useCallback, useEffect, useState from 'react';
import useTranslation from 'react-i18next';
import languages, useTypedTranslation from '../definitions/language';
import matchPath, useHistory from 'react-router-dom';
import routes from '../definitions/routes';
import MeegoTech from '../assets/meego.svg';
import Theme, createStyles, AppBar, Box, FormControlLabel, FormGroup, IconButton, Menu, MenuItem, Toolbar, Typography, Switch, useMediaQuery from '@mui/material';
import makeStyles from '@mui/styles';
import PersonOutline from '@mui/icons-material';
import MenuIcon from '@mui/icons-material/Menu';
import ThemeSwitcher from '../theme/themeSwitcher';
import useDispatch from 'react-redux';
import Dispatch from '../store/configureStore';
const Navigation: React.FC = () =>
//Authentication
const [auth, setAuth] = React.useState(true);
const [anchorEl, setAnchorEl] = React.useState<null | htmlElement>(null);
//Translation
const t = useTypedTranslation();
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setAuth(event.target.checked);
;
const handleMenu = (event: React.MouseEvent<HTMLElement>) =>
setAnchorEl(event.currentTarget);
;
const handleClose = () =>
setAnchorEl(null);
;
// Get OS-level preference for dark mode
const prefersDarkMode: boolean | undefined = useMediaQuery("(prefers-color-scheme: dark)");
//This Function throws the error
function DispatchThemes(themeMode: boolean | undefined)
const dispatch = useDispatch<Dispatch>()
useEffect(() =>
dispatch.themeModel.setDarkModeAsync(themeMode);
, [])
return <></>
return (
<Box sx= flexGrow: 1 >
<FormGroup>
<FormControlLabel
control=
<Switch
color="default"
checked=auth
onChange=handleChange
aria-label="login switch"
/>
label=auth ? 'Logout' : 'Login'
/>
</FormGroup>
<AppBar position="static" style= backgroundColor: "rgb(255,255,255" >
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx= mr: 2
>
<MenuIcon fontSize="large" style= color: "rgb(0,0,0)" />
</IconButton>
<img src=MeegoTech style= height: "100px", width: "auto", marginRight: "15px" />
<Typography variant="h6" component="div" sx= flexGrow: 1 style= color: "rgb(0,0,0)" >
t("layout", "meegoTech")
</Typography>
/* If i'll switch this switcher the error will be thrown */
<ThemeSwitcher useOs=false themeChanger=DispatchThemes />
auth && (
<div>
<IconButton
size="large"
style= color: "rgb(0,0,0)"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick=handleMenu
>
<PersonOutline fontSize="large" />
</IconButton>
<Menu
id="menu-appbar"
anchorEl=anchorEl
anchorOrigin=
vertical: 'top',
horizontal: 'right',
keepMounted
transformOrigin=
vertical: 'top',
horizontal: 'right',
open=Boolean(anchorEl)
onClose=handleClose
>
<MenuItem onClick=handleClose>Profile</MenuItem>
<MenuItem onClick=handleClose>My account</MenuItem>
</Menu>
</div>
)
</Toolbar>
</AppBar>
</Box>
);
export default Navigation
这是ThemeSwitcher
的代码:
interface ThemeSwitcherOptions
useDark?: boolean;
themeChanger: (useDark?: boolean) => void;
const ThemeSwitcher: React.FC<ThemeSwitcherOptions> = (props) =>
const expandedProps =
...props,
useDark: props.useDark || false,
;
const [theme, setTheme] = useState(expandedProps);
const handleSwitch = (_e: any, checked: boolean) =>
setTheme( ...theme, useDark: checked );
theme.themeChanger(checked);
;
return (
<>
<FormControlLabel
style=color:'rgb(0,0,0)'
labelPlacement="end"
label=""
control=
<ThemeSwitch
checked=theme.useDark
onChange=handleSwitch
/>
/>
</>
);
export default ThemeSwitcher;
有人知道为什么会抛出错误吗?
【问题讨论】:
themeChanger=DispatchThemes 是一个事件吗?如果是,那么我们将违反 hooks 实现。文档说“不要调用事件处理程序”。请提供有关 ThemeSwitcher 的更多信息。我不确定,但我认为这可能会导致问题。 请贴出ThemeSwitcher
的代码。至少与themeChanger
prop 相关的部分。
@GabrielePetrioli 我添加了代码并尝试了一点,但我无法让它工作
【参考方案1】:
你的DispatchThemes
是一个组件,你甚至返回 jsx。但是您将它作为themeChanger
传递给ThemeSwitcher
组件并在事件处理程序中以theme.themeChanger
的形式调用它。所以你不要把它当作一个组件。 Hooks 只能在被渲染的组件中使用。
您可以将 DispatchThemes 函数更改为
const dispatch = useDispatch<Dispatch>(); // put the dispatch outside the function
//This function should not throw an error anymore
function DispatchThemes(themeMode: boolean | undefined)
// remove the useEffect as well
dispatch.themeModel.setDarkModeAsync(themeMode);
【讨论】:
以上是关于rematchjs 上的 Hook 调用无效的主要内容,如果未能解决你的问题,请参考以下文章