繁体   English   中英

当我尝试更改 useEffect() 中的状态时,“无法对未安装的组件执行 React 状态更新”

[英]"Can't perform a React state update on an unmounted component" when i try to change state in useEffect()

我有一个材质抽屉组件,当组件挂载时,需要检查本地存储并获取登录用户,然后将用户名放入模板中。

这是我的组件:

const PersistentDrawer = () => {

  const [userLogged, setUserLogged] = useState({});
  useEffect(() => {
    setUserLogged(JSON.parse(localStorage.getItem('currentUser')))
        // eslint-disable-next-line react-hooks/exhaustive-deps
    },[])
  const classes = drawerStyles();
  const theme = useTheme();
  const [open, setOpen] = useState(false);

  const handleDrawerOpen = () => {
    setOpen(true);
  };

  const handleDrawerClose = () => {
    setOpen(false);
  };

  return (
    <div className={classes.root}>
        <CssBaseline />
        <AppBar
            position="fixed"
            className={clsx(classes.appBar, {
            [classes.appBarShift]: open,
            })}
        >        
            <Toolbar>
            <IconButton
                color="inherit"
                aria-label="open drawer"
                onClick={handleDrawerOpen}
                edge="start"
                className={clsx(classes.menuButton, open && classes.hide)}
            >
                <MenuIcon />
            </IconButton>
            <Typography variant="h6" noWrap>
                Persistent drawer
            </Typography>
            </Toolbar>
        </AppBar>
        <Drawer
            className={classes.drawer}
            variant="persistent"
            anchor="left"
            open={open}
            classes={{
            paper: classes.drawerPaper,
            }}
        >
            <img className={classes.logo} alt="Incca Sistemas" src="/assets/logo-incca.png"></img>          
            <div className={classes.drawerHeader}>
        <Typography component="h6">{userLogged.login}</Typography>
            <IconButton onClick={handleDrawerClose}>
                {theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
            </IconButton>
            </div>
            <Divider />
            <List>
            {['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
                <ListItem button key={text}>
                <ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
                <ListItemText primary={text} />
                </ListItem>
            ))}
            </List>
            <Divider />
        </Drawer>
        <main
            className={clsx(classes.content, {
            [classes.contentShift]: open,
            })}
        >
        </main>
    </div>
  );
}

export default PersistentDrawer

我收到:

无法对卸载的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。

我该如何解决这个问题?

将您的useEffect更改为如下所示:

useEffect(() => {
  let neverMind = false;

  const currentUser = JSON.parse(localStorage.getItem('currentUser'))

  if(!neverMind) setUserLogged(currentUser)
  return () => ( neverMind = true);
},[])

不知何故,您的组件正在卸载,但即使已卸载 - 您仍在尝试更新其状态。 为避免这种情况,设置一个标志,让您知道组件何时卸载(在返回的函数中),并且仅在标志未更改时才更新状态。

有关如何使用“清理功能”的另一个示例,请参阅 React 文档 - https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

这是丹·阿布拉莫夫对这个问题的回答的链接 - https://github.com/facebook/react/issues/14369#issuecomment-468267798

无法对卸载的组件执行 React 状态更新。

当尝试更改尚不存在的组件时会发生此错误。

这通常是组件并行初始化(异步)的结果。

例如:假设两个组件 A、B 都在第 1、2 行异步初始化。在第 3 行中,如果组件 A 尝试更新组件 B,则组件 B(第 2 行)很可能没​​有被创建时间线 3(更新到 B)被执行。

在这种情况下,会报上述错误。

怎么修? 识别并更改异步代码块或函数,以确保在创建组件之前不会尝试对其进行更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM