I have an Upvote component in my React/TypeScript app that allows user to upvote a post, or remove their upvote. the upvote itself is an icon from the react-icons
package, specifically from the Grommet-Icons section. When a user upvotes a post by clicking on the icon, I dynamically change the fill of the icon like this:
e.target.querySelector("path").setAttribute("fill", "green");
e.target
is an SVG element. Within that element, I use querySelector
to find its path
child. On the path
child, I set its 'fill' attribute to green.
This works fine, but I want to extend it. When I render each post, I check if the user that's logged in already upvoted that specific post. I want to change the color of the icon based on the boolean result of whether the user already upvoted the post or not, so this way the icon can already be green and the user will see that they already upvoted the post. My question is how can I access that 'fill' attribute WITHOUT the e.target
- since the user hasn't clicked on anything when the page loads. I guess my question is pretty specific to the usage of the react-icons
package, because when I add an icon to my return function, it's wrapped by a wrapper component, so I can't access the path
element (In this case the component is GrSign
).
Here is the Upvote component for context:
import React, { useEffect, useState } from "react";
import { GrSign } from "react-icons/gr";
import { useSelector } from "react-redux";
import { InitialState } from "../store/reducers/rootReducer";
export const Upvote = (props: any) => {
const userState = useSelector((state: InitialState) => {
return state.auth;
});
const [upvoted, setUpvoted] = useState(false);
useEffect(() => {
if (userState && userState.user !== undefined) {
const userId = userState.user.user._id;
if (props.upvotes.indexOf(userId) > -1) {
// The user already upvoted this post
setUpvoted(true);
}
}
if (upvoted) {
}
}, []);
const handleClick = (e: any) => {
console.log(e.target);
e.target.querySelector("path").setAttribute("fill", "red");
};
return (
<div className="flex items-center">
<GrSign
size="2em"
className="transform transition duration-300 hover:scale-125"
onClick={handleClick}
/>
<div className="pl-2 text-lg">{props.upvotes.length}</div>
</div>
);
};
in the useEffect
function, I would like to add a line that will change the color of the icon if upvoted === true
.
Just in case this helps, this is what gets printed to the console when I write console.log(e.target)
inside the handleClick
function:
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" class="transform transition duration-300 hover:scale-125" height="2em" width="2em" xmlns="http://www.w3.org/2000/svg"><path fill="red" stroke="#000" stroke-width="2" d="M8,23 C10,23 12.9996892,23 15,23 C18,23 19,21 19,18 L19,6 C19,4.00000008 18,3.99999992 17.5,4 C17,4.00000008 15.9998779,4.00000008 15.9998779,5.99999984 L15.9998779,13 C15.9998777,12 16.0001888,10.9999999 14.5003109,10.9999999 C13.000433,10.9999999 13,13 13,13 C13,12 13,11 11.5,10.9999999 C10,10.9999999 10,12 10,12.9999999 L10,4 C10,3 10.029402,2 8.5,2 C7,2 7,3 7,4 L7,18 L7,14 C7,13 6.44999986,12 5.00000005,12 C5,12 4,12 4,12 C4,12 4.00000001,14.0384045 4,18 C3.99999999,21.9615955 6,23.023861 8,23 Z"></path></svg>
class
directly for condition? – Shubham Verma