Reputation: 503
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?
Upvotes: 2
Views: 921
Reputation: 2053
First - you should avoid querying dom inside react app. You can create state for holding your class or styles and then pass it to component.
Second - remove empty array from useEffect it should help.
Upvotes: 1
Reputation: 10382
your code only runs on mount with empty array dependency, hence any change on props won't be reflected. that's the most likely the problem here.
fwiw your code is rather complicated and it's better to avoid manipulating the DOM directly, it would much simpler if you create a dictionary to apply your style to your element like:
const colors = {
youtube: "#DC143C",
blog: "#00FFFF",
instagram: "#FF88FF",
twitter: "#3366FF",
}
const ProductCard = ({ category }) => {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardContent className={classes.content}>
<Typography id="category" style={{ color: colors[category] }} className={classes.category} component="p">
{category}
</Typography>
</CardContent>
</Card>
)
}
export default ProductCard
Upvotes: 1
Reputation: 6362
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.
I'm not familiar with your exact components, so not all of these will work for you. But at least one should.
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
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
Upvotes: 0