Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I make onClick events work with specific elements in a .map() function?

I’m trying to make a list of users inside a chat. Each user is supposed to have a button opening a menu, allowing admins to ban that specific user. I’m mapping an array of users to get the list, but the issue is that whenever I try to click on the ‘ban’ button, the user data seems to always be for the last user in the array, instead of the user on which I clicked. Here’s the code for the entire component:

const UserList: React.FC<{channel: string}> = ({channel}) => {
    const [channelMembers, setChannelMembers] = useState<any[] | null>(null)
    const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
    const [isAdmin, setIsAdmin] = useState(false)
    const navigate = useNavigate()
    const open = Boolean(anchorEl)
    const baseUrl = useContext(UrlContext)

    useEffect(() => {
        axios.get(baseUrl + `chat/${channel}/users`, {withCredentials: true}).then((response) => {
            setChannelMembers(response.data)
        })
    }, [baseUrl, channel, anchorEl])

    useEffect(() => {
        axios.get(baseUrl + `users/me`, {withCredentials: true}).then((response) => {
            axios.get(baseUrl + `chat/${channel}/admins`, {withCredentials: true}).then((resp2) => {
                if (resp2.data.includes(response.data.id)) {
                    setIsAdmin(true)
                }
            }).catch((error) => {
                console.log(error)
            })
        }).catch((error) => {
            console.log(error)
        })
    }, [baseUrl, anchorEl])

    const handleClick = (event: React.MouseEvent<HTMLElement>) => {
        setAnchorEl(event.currentTarget)
    }

    const handleClose = () => {
        setAnchorEl(null)
    }
    
    const handleBan = (user: any) => () => {
        let banUser = {...user}

        console.log(banUser)
        axios.post(baseUrl + `chat/${channel}/ban`, banUser, {withCredentials: true}).catch((error) => {
            console.log(error)
        })
        handleClose()
    }

    return (
        <>
        <Drawer
            sx={{
                width: drawerWidth,
                flexShrink: 0,
                '& .MuiDrawer-paper': {
                    width: drawerWidth,
                    boxSizing: 'border-box',
                },
            }}
            variant="permanent"
            anchor="right"
        >
            <Toolbar />
            <List>
                {channelMembers?.map((user: any, index: number) => {

                    return (
                        <Fragment key={index}>
                            <ListItem>
                                <ListItemText primary={user.name} />
                                <ListItemIcon>
                                    {(user.status === Status.ONLINE) ? <CircleIcon style={{color: "green"}} fontSize="small" /> : <RadioButtonUncheckedIcon style={{color: "grey"}} fontSize="small" />}
                                </ListItemIcon>
                                <IconButton
                                    aria-label="more"
                                    id="long-button"
                                    aria-controls={open ? 'long-menu' : undefined}
                                    aria-expanded={open ? 'true' : undefined}
                                    aria-haspopup="true"
                                    onClick={handleClick}
                                >
                                    <MoreVertIcon />
                                </IconButton>
                                <Menu
                                    id="long-menu"
                                    MenuListProps={{
                                        'aria-labelledby': 'long-button'
                                    }}
                                    anchorEl={anchorEl}
                                    open={open}
                                    onClose={handleClose}
                                >
                                    {isAdmin &&
                                    [<MenuItem onClick={handleClose}>
                                        <Typography>
                                            Make admin
                                        </Typography>
                                    </MenuItem>,
                                    <MenuItem onClick={handleClose}>
                                        <Typography>
                                            Mute
                                        </Typography>
                                    </MenuItem>,
                                    <MenuItem onClick={handleClose}>
                                        <Typography>
                                            Kick
                                        </Typography>
                                    </MenuItem>,
                                    <MenuItem onClick={handleBan(user)}>
                                        <Typography>
                                            Ban
                                        </Typography>
                                    </MenuItem>]}
                                    <MenuItem onClick={handleClose}>
                                        <Typography>
                                            View profile
                                        </Typography>
                                    </MenuItem>
                                    <MenuItem onClick={handleClose}>
                                        <Typography>
                                            Invite to play
                                        </Typography>
                                    </MenuItem>
                                </Menu>
                            </ListItem>
                            <hr />
                        </Fragment>
                    )
}               )}
            </List>
        </Drawer>
        </>
    )
}

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

You’re rendering multiple menus in your map and since you’re using only one state when opening one menu it sets open to true which means all menus are open because of this prop open={open}.

You should try to render only one Menu and possibly store in a state the selected user. There’s probably a better way to do this but it should solve your problem.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading