reactjs - 错误:每次调整屏幕大小后,呈现的挂钩数量少于预期
问题描述
我正在创建响应式导航栏,并且在渲染时效果很好。每次屏幕调整大小或切换到移动视图后,我都会收到错误消息:“错误:渲染的钩子比预期的少。这可能是由意外的提前返回语句引起的。”
133 |
134 | useEffect(() => {
135 | const setResponsiveness = () => {
> 136 | return window.innerWidth < 900
137 | ^ ? setState((prevState) => ({ ...prevState, mobileView: true }))
138 | : setState((prevState) => ({ ...prevState, mobileView: false }));
139 | };
140 |
141 | setResponsiveness();
142 |
> 143 | window.addEventListener("resize", () => setResponsiveness());
144 | ^ }, []);
145 |
146 | const displayDesktop = () => {
检查窗口宽度后,我只想将移动视图的状态更改为 false 或 true,然后调用 displayDesktop 或 displayMobile 函数。
包含最重要部分的简码:
export default function Navbar() {
const {
header,
toolbar,
drawerContainer,
largeIcon,
logo,
desktopList,
} = useStyles();
const [state, setState] = useState({
mobileView: false,
drawerOpen: false,
});
const { mobileView, drawerOpen } = state;
useEffect(() => {
const setResponsiveness = () => {
return window.innerWidth < 900
? setState((prevState) => ({ ...prevState, mobileView: true }))
: setState((prevState) => ({ ...prevState, mobileView: false }));
};
setResponsiveness();
window.addEventListener("resize", () => setResponsiveness());
}, []);
const displayDesktop = () => {
return (
<ThemeProvider theme={theme}>
<Toolbar className={toolbar}>
<div className={logo}>
<MotorcycleRoundedIcon className={largeIcon} fontSize="large" />
<Typography variant="h6" fontFamily="Arial" color="inherit" noWrap>
Title
</Typography>
</div>
<div className={desktopList}>
{GetStatsButton()} {GetResultsButton()} {GetTablesButton()}
{GetCalendarButton()}
</div>
</Toolbar>
</ThemeProvider>
);
};
const displayMobile = () => {
const handleDrawerOpen = () =>
setState((prevState) => ({ ...prevState, drawerOpen: true }));
const handleDrawerClose = () =>
setState((prevState) => ({ ...prevState, drawerOpen: false }));
return (
<ThemeProvider theme={theme}>
<Toolbar>
<IconButton
{...{
edge: "start",
color: "inherit",
"aria-label": "menu",
"aria-haspopup": "true",
onClick: handleDrawerOpen,
}}
>
<MenuIcon />
</IconButton>
<Drawer
{...{
anchor: "top",
open: drawerOpen,
onClose: handleDrawerClose,
variant: "temporary",
}}
>
<div className={drawerContainer}>{getDrawerChoices()}</div>
</Drawer>
<MotorcycleRoundedIcon className={largeIcon} fontSize="large" />
<Typography variant="h6" fontFamily="Arial" color="inherit" noWrap>
Title
</Typography>
</Toolbar>
</ThemeProvider>
);
};
return (
<header>
<AppBar className={header}>
{mobileView ? displayMobile() : displayDesktop()}
</AppBar>
</header>
);
}
有人可以给我一个提示吗?我知道这与在条件内调用 Hooks 有关,但我不知道如何重新格式化它。
解决方案
您正在从常规 JS 函数调用 React 钩子,这违反了钩子规则。例如,您在调用时这样做GetStatsButton()
,因为所有这些组件都包含useSate
调用。
您可以通过更改来解决此问题:
<div className={desktopList}>
{GetStatsButton()} {GetResultsButton()} {GetTablesButton()}
{GetCalendarButton()}
</div>
到
<div className={desktopList}>
<GetStatsButton />
<GetResultsButton />
<GetTablesButton />
<GetCalendarButton />
</div>
为了突出这些是 React 组件这一事实,最好从名称中删除Get 。
此外,您的StyledMenuItem
andStyledMenu
应该只在这些组件之外定义一次,然后您可以在需要它们的任何地方重用它们。
最后但并非最不重要的一点是,您可能想看看 MUI 的useMediaQuery以实现您想要的响应行为。
推荐阅读
- c++ - 访问继承的函数
- java - 导出文档时窗口关闭,无法切换到父窗口
- java - 实时应用,Reactor Netty vs Netty
- python - Kivy AnchorLayout .Kv 文件
- java - 使用提供的 json 字符串创建模型
- javascript - View 中 input type="time" 值的变化不会反映在 Model of Angular 中
- angular - 一些空闲时间后角度可观察对象不调用
- c++ - 如果数据类型未知,如何打印 void 指针的值?
- python-3.x - pandas 自定义排序多级索引
- hibernate - JPQL 多连接提取返回错误“无法同时提取多个包”