My Fixtures.js code:
const [selectedButton, setSelectedButton] = useState(1);
console.log("selected button = ",selectedButton);
const dateClick = (e) => {
const clcikedDivId = e.currentTarget.id;
// some code here!
setSelectedButton(clcikedDivId);
}
};
<div className={classes.roundDatesContainer}>
{roundDates.map((item, index) => (
<Button
id={index 1}
key={index}
lowOpacity={index 1 !== selectedButton ? true : false}
className="primary"
customCssStyle={customCssStyle}
click={dateClick}
>
{item}
</Button>
))}
</div>
In my above code snippet, I have a round dates array which I'm iterating over with the map function and for each item I'm outputting a Button component that will have an id property equal to index 1 and a lowOpacity property of true in case the index 1 is different from the selectedButton value and false otherwise. In addition it has a click property that tells the button to execute the dateClick function when the button is clicked, and this function will execute some code (that doesn't matter for this question) and at the end of the fucntion the selectedButton value will be set to the clicked button id
My Button component:
function Button(props) {
const { id, type, click, className, lowOpacity, customCssStyle } = props;
console.log("id = ", id, " & low opacity from btn componenet = ", lowOpacity);
return (
<button
id={id}
type={type || "button"}
onClick={
click ||
(() => {
return;
})
}
className={`${classes[className || ""]} ${lowOpacity ? classes.lowOpacity : undefined}`}
>
<span style={{ ...customCssStyle }}>{props.children}</span>
</button>
);
}
As you can see in this component I'm setting a class of lowOpacity to the button in case that prop is set to true (which will be true when index 1 is different from the selectedButton value).
Now when the page first loads I get the following correct result:

(Note that I have react strict mode on which is why the fixtures.js is loading twice)
Since at first the selectedButton value defaults to 1 and index 1 is equal to 1 that means all buttons except the first 1 will have their lowOpacity property set to true (though there is also an undefined value for a Button with an id of undefined which I have no idea where did that come from).
The problem is when I click on another button all buttons will now have the lowOpacity propert set to true:
For some reason when I click the second (or third) Button the selectedButton changes and become equal to the id of that clicked Button however as you can see from the above image all of the Button components now have their lowOpacity property set to true (plus one of undefined for a button of id undefined which I have no idea where that came from)
CodePudding user response:
The issue here is that IDs are treated as strings in the DOM, so here: index 1 !== selectedButton (Where selectedButton is set from e.currentTarget.id)
You are comparing a number to a string, and they will never be equal, so !== will always return true
E.g.
function example(e) {
console.log(e.currentTarget.id)
console.log(1 === e.currentTarget.id)
}
<input id="1" onClick="example(event)" placeholder="Click me" />
You will need to either:
- Convert the
index 1to a string before comparing the values - Parse the ID as a number before the comparison
- Parse the ID as a number before storing it to
selectedButton
I would recommend replacing:
const clcikedDivId = e.currentTarget.id
with
const clcikedDivId = parseInt(e.currentTarget.id)

