Home > database >  Infinite Loop When I Update State After OnClick Event
Infinite Loop When I Update State After OnClick Event

Time:10-30

So I'm trying to trigger a menu popup after I click an icon button.

I'm using MUI,

So I copied the demo code to test it out,

 <div>
            <IconButton onClick={handleOpenMenu} 
             aria-controls={open ? 'basic-menu' : undefined}
             aria-haspopup="true"
             aria-expanded={open ? 'true' : undefined}
            >
              <MoreVertIcon />
            </IconButton>

            <Menu
              id="demo-positioned-menu"
              aria-labelledby="demo-positioned-button"
              anchorEl={anchorEl}
              open={open}
              onClose={handleMenuClose}
              anchorOrigin={{
                vertical: 'top',
                horizontal: 'left',
              }}
              transformOrigin={{
                vertical: 'top',
                horizontal: 'left',
              }}
            >
              <MenuItem onClick={handleMenuClose}>Profile</MenuItem>
              <MenuItem onClick={handleMenuClose}>My account</MenuItem>
              <MenuItem onClick={handleMenuClose}>Logout</MenuItem>
            </Menu>
            </div>

And here are the event handlers,

  const [anchorEl, setAnchorEl] = useState(null);
  const open = Boolean(anchorEl);
  const handleOpenMenu = (event) => {
    setAnchorEl(event.currentTarget);
  };
  const handleMenuClose = () => {
    setAnchorEl(null);
  };

But whenever I press on the IconButton, it freezes the whole UI and prints my Firebase OnAuthStateChanges function in an infinite loop for some reasons.

  var unsubscribe = onAuthStateChanged(auth, (user) => {
    if (user) {
      const uid = user.uid;
      console.log(uid)
      setAuthenticated(true)

    } else {
 
      setAuthenticated(false)

    }
  });

Any suggestions on what I'm doing wrong?

CodePudding user response:

The infinite loop is caused by the onAuthStateChanged observer. The function sets a listener that fires and causes the component to rerender. The new render sets another listener that fires, and so on. Even unsubscribing won't help in this situation.

A possible fix would be to wrap it in a useEffect hook with an empty dependency array.

useEffect(() => {
    onAuthStateChanged(auth, (user) => {
        //your user logic...
        if (user) {
            setAuthenticated(true);
        } else {
            setAuthenticated(false);
        }
    });
}, []);
  • Related