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);
}
});
}, []);