pxl9588
pxl9588

Reputation: 42

How can I change the color of a child component when clicked?

I have multiple 'Rectangle' components in a 'Wall' that should change color when clicked. The onClick in 'Rectangle' is used in another Component that will make the 'Rectangle' hidden or not. I tried to do something similar here, but I can't change variables inside the 'Rectangle' component.

My attempt

customClickEvent={() =>{this.props.color = hidden_dictionary[count];}}

Wall.js

const [count, setCount] = useState(0);
    const color_dictionary = {0: "bg-red-400", 1: "bg-blue-400", 2:"bg-green-400", 3:"bg-yellow-400"};

    return (
        <div className="grid grid-flow-col grid-rows-4 lg:py-20 gap-y-1 gap-x-1 lg:gap-y-6 lg:gap-x-6 justify-center items-center">
            <Rectangle type="wall">Fiji</Rectangle>
            <Rectangle type="wall">Hazelnut</Rectangle>
            <Rectangle type="wall">Mocha</Rectangle>
            <Rectangle type="wall">Australia</Rectangle>
            <Rectangle type="wall">Cook Islands</Rectangle>
            <Rectangle type="wall">Cube</Rectangle>
            <Rectangle type="wall">Vanilla</Rectangle>
            <Rectangle type="wall">Butter Pecan</Rectangle>
            <Rectangle type="wall">San Pellegrino</Rectangle>
            <Rectangle type="wall">Coconut</Rectangle>
            <Rectangle type="wall">Papua New Guinea</Rectangle>
            <Rectangle type="wall">Caramel</Rectangle>
            <Rectangle type="wall">Prince</Rectangle>
            <Rectangle type="wall">Guam</Rectangle>
            <Rectangle type="wall">Champagne</Rectangle>
            <Rectangle type="wall">T</Rectangle>
        </div>  
    )

Rectangle.js

    //ANSWER
    if(props.type === "answer") {
        width = "p-2";
        height = "h-12 lg:h-20";
        text_size = "text-2xl sm:text-4xl lg:text-5xl";
    }

    //WALL
    else if (props.type === "wall")
    {
        width = "w-20 sm:w-24 lg:w-52  cursor-pointer";
        height = "h-16 sm:h-20 lg:h-40";
        text_size = "text-1xl lg:text-4xl";
        color = props.color;
    }

    //VOWELS
    else if (props.type === "vowels")
    {
        width = "p-4";
        height = "";
        text_size = "text-3xl sm:text-4xl lg:text-5xl";
        color = "bg-blue-800 text-white";
    }

    else
    {
        width = "w-16 sm:w-36 lg:w-80";
        height = "h-12 sm:h-28 lg:h-64";
        text_size = "text-2xl sm:text-6xl lg:text-8xl";
    }

    return (
      <div onClick={props.customClickEvent} className={width + " " + height + " " + props.color + " " + " shadow-2xl rounded-md " + props.hidden}>
         <h1 className={text_size + " w-full h-full flex justify-center items-center text-center"}>{props.children}</h1>
        </div>)

Upvotes: 0

Views: 224

Answers (2)

Tom Jardine-McNamara
Tom Jardine-McNamara

Reputation: 2618

Props aren’t designed to be mutable. In other words, setting a new value on this.props.color won’t cause the rectangle to re-render. Even if it did, the value of this in your callback will be for the instance of Wall, because you’re using an arrow function, which inherits its this from the surrounding scope.

One solution would be to have your Wall component store the colour of each Rectangle as state, and pass that via the color prop. Your callback handler could then change the colour. However, because you have multiple Rectangles, you would need some way of distinguishing between them an index or perhaps ID.

If it’s not important for your Wall to know whether the Rectangle has been clicked, then it would be simpler to define the click handler inside Rectangle and have it modify state in the Rectangle, i.e:

const [color, setColor] = useState();

return (
<div onClick={() => setColor(‘new colour’)} className={width + " " + height + " " + color + " " + " shadow-2xl rounded-md " + props.hidden}>
         <h1 className={text_size + " w-full h-full flex justify-center items-center text-center"}>{props.children}</h1>
        </div>)

Upvotes: 3

AdamKniec
AdamKniec

Reputation: 1727

Have You tried toggling the CSS class onClick ? That class would be styled according to Your needs. The only thing You have to do it do dynamically add a class.

Upvotes: 0

Related Questions