当我尝试更改useEffect()中的状态时,“无法在已卸载的组件上执行React状态更新”

时间:2020-03-05 18:17:25

标签: reactjs material-ui

我有一个材料抽屉组件,在安装该组件时,需要检查本地存储并获取登录用户,然后将用户名放在模板中。

这是我的组件:

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清理中的所有订阅和异步任务 功能。

我该如何解决?

2 个答案:

答案 0 :(得分:0)

将您的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

以下是Dan Abramov对这个问题的答案的链接-https://github.com/facebook/react/issues/14369#issuecomment-468267798

答案 1 :(得分:0)

无法在已卸载的组件上执行React状态更新。

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

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

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

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

如何解决? 确定并更改异步代码块或函数,以确保在创建组件之前不尝试对其进行更新。