Rob Irvin
Rob Irvin

Reputation: 121

React useStyles Remove class name on click

This is almost certainly the easiest thing in the world but is somehow evading me....

I have a selection of material-ui card components that are selectable onClick and as such should add a class when it's selected. For some reason the removal of the class isn't applying despite all the examples seeming to suggest it should. What am I doing wrong?

Cut down for brevity...

const useStyles = makeStyles((theme: Theme) =>
    createStyles({
        cardSelected: {
            backgroundColor: theme.palette.action.selected
        },
    })
);


export const Occasion = (): JSX.Element => {
    const classes = useStyles();
    const [selected, setSelected] = useState<string>('');

    const handleSelect = (e: React.MouseEvent) => {
        const s = e.currentTarget.getAttribute("data-option");
        if (s) {
            setSelected(s);
        }
    }

    return (
        <Grid item xs={12} sm={6} md={3}>
            <CardActionArea className={classes.actionArea} onClick={handleSelect} data-option={occasion.id}>
                <Card className={ selected === occasion.id ? classes.cardSelected : '' }>
                    <IconRounded className={classes.iconItem} color="secondary" />
                    <Typography variant="h5" component="h3">{ occasion.name } </Typography>
                </Card>
            </CardActionArea>
        </Grid>
    );
}

```


Clicking a card correctly adds the desired class but does not remove it from the other card items?

Upvotes: 0

Views: 411

Answers (1)

Mehul Thakkar
Mehul Thakkar

Reputation: 2447

You also need to clear the selected.

const useStyles = makeStyles((theme: Theme) =>
    createStyles({
        cardSelected: {
            backgroundColor: theme.palette.action.selected
        },
    })
);


export const Occasion = (): JSX.Element => {
    const classes = useStyles();
    const [selected, setSelected] = useState<string>('');

    const handleSelect = (e: React.MouseEvent) => {
        const s = e.currentTarget.getAttribute("data-option");
        if (s) {
            setSelected(s);
        } else {
            setSelected('');
        }
    }

    return (
        <Grid item xs={12} sm={6} md={3}>
            <CardActionArea className={classes.actionArea} onClick={handleSelect} data-option={occasion.id}>
                <Card className={ selected === occasion.id ? classes.cardSelected : '' }>
                    <IconRounded className={classes.iconItem} color="secondary" />
                    <Typography variant="h5" component="h3">{ occasion.name } </Typography>
                </Card>
            </CardActionArea>
        </Grid>
    );
}

In the current example, you're just adding it to selected if id or s exists but not removing it.

EDIT Updated with toggle functionality.

const useStyles = makeStyles((theme: Theme) =>
    createStyles({
        cardSelected: {
            backgroundColor: theme.palette.action.selected
        },
    })
);


export const Occasion = (): JSX.Element => {
    const classes = useStyles();
    const [selected, setSelected] = useState<string>('');

    const toggleSelect = (e: React.MouseEvent) => {
        const s = e.currentTarget.getAttribute("data-option");
        if (s && !selected) {
            setSelected(s);
        } else {
            setSelected('');
        }
    }

    return (
        <Grid item xs={12} sm={6} md={3}>
            <CardActionArea className={classes.actionArea} onClick={toggleSelect} data-option={occasion.id}>
                <Card className={ selected === occasion.id ? classes.cardSelected : '' }>
                    <IconRounded className={classes.iconItem} color="secondary" />
                    <Typography variant="h5" component="h3">{ occasion.name } </Typography>
                </Card>
            </CardActionArea>
        </Grid>
    );
}

Upvotes: 1

Related Questions