change color depending on value with javascript

I’m using React and want to change text color depends on the value. The code looks like this:

const ProductCard = (props) => {
    const classes = useStyles();

    useEffect(() => {
        const category = document.getElementById('category');

        if(props.category === "youtube"){
            category.style.color="#DC143C";
        }
        if(props.category === "blog"){
            category.style.color="#00FFFF";
        }
        if(props.category === "instagram"){
           category.style.color="#FF88FF";
        }
        if(props.category === "twitter"){
            category.style.color="#3366FF";
        }
    }, []);

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <Typography id="category" className={classes.category} component="p">
                    {props.category}
                </Typography>
            </CardContent>
        </Card>
    )
}

export default ProductCard

With this code, only the first value of the element is changed, the rest are not. What I’m doing wrong?

Answer

When you get an element by id, only one element is returned.

const category = document.getElementById('category'); // referring to this line

That’s because technically, ids should be unique. Only one element should have the id category on the page. So when you set the style on container, only one element is changed because it is only one element.

Additionally, ids are not scoped to a specific component. So if you have multiple ProductCard components, getElementById will always return the category of the first ProductCard component.

Solutions

I’m not familiar with your exact components, so not all of these will work for you. But at least one should.

Use a color prop

If your Typography component accepts a color or style prop, use that. Then, you’re telling React “this specific component should have this color”.

const colors = {
    youtube: "#DC143C", 
    blog: "#00FFFF", 
    instagram: "#FF88FF", 
    twitter: "#3366FF", 
}

const ProductCard = (props) => {
    const classes = useStyles();

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
                    {props.category}
                </Typography>
            </CardContent>
        </Card>
    )
}

export default ProductCard

Use a wrapper component

You may be able to wrap a div around just the typography and set the text color that way. Not the best option, but it will work.

const colors = {
    youtube: "#DC143C", 
    blog: "#00FFFF", 
    instagram: "#FF88FF", 
    twitter: "#3366FF", 
}

const ProductCard = (props) => {
    const classes = useStyles();

    return (
        <Card className={classes.root}>
            <CardContent className={classes.content}>
                <div style={{ color: colors[props.category] }}>
                    <Typography id="category" className={classes.category} component="p" style={{ color: colors[props.category] }}>
                        {props.category}
                    </Typography>
                </div>
            </CardContent>
        </Card>
    )
}

export default ProductCard

Leave a Reply

Your email address will not be published. Required fields are marked *