【问题标题】:Error: Rendered fewer hooks than expected after each screen resize错误:每次调整屏幕大小后,呈现的挂钩数量少于预期
【发布时间】:2021-05-16 17:35:59
【问题描述】:

我正在创建响应式导航栏,它在渲染时运行良好。每次屏幕调整大小或切换到移动视图后,我都会收到错误消息:“错误:渲染的钩子比预期的少。这可能是由意外的提前返回语句引起的。”

  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 有关,但我不知道如何重新格式化它。

【问题讨论】:

  • 我认为您的这部分代码没有问题。它似乎工作正常,这可能与您拥有的其他组件有关。禁用它们中的每一个,直到错误消失,然后您将对其进行跟踪。
  • 请提供一个code sandbox 来重现您的问题。
  • 感谢您的快速回答。这是代码:codesandbox.io/s/…

标签: reactjs material-ui


【解决方案1】:

您正在从常规 JS 函数调用 React 钩子,这违反了Rules of Hooks。例如,在调用GetStatsButton() 时,您会这样做,因为所有这些组件都包含useSate 调用。

您可以通过更改来解决此问题:

<div className={desktopList}>
  {GetStatsButton()} {GetResultsButton()} {GetTablesButton()}
  {GetCalendarButton()}
</div>

<div className={desktopList}>
  <GetStatsButton />
  <GetResultsButton />
  <GetTablesButton />
  <GetCalendarButton />
</div>

为了强调这些是 React 组件这一事实,最好从名称中删除 Get

此外,您的 StyledMenuItemStyledMenu 应该只在这些组件外部定义一次,然后您可以在任何需要它们的地方重复使用它们。

最后但同样重要的是,您可能需要查看 MUI 的 useMediaQuery 以实现您想要的响应行为。

【讨论】:

    猜你喜欢
    • 2021-05-09
    • 2015-06-17
    • 2013-11-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多