Reputation: 49
I'm new to hooks and I encountered a problem using them. I have two components:
const Button = ({ isHidden, icon, onClick }) => {
return (
<div>
{isHidden ? (
<button className="tile" onClick={onClick} />
) : (
<button className="tile" onClick={onClick}>
<i className={icon} />
</button>
)}
</div>
);
};
const Board = () => {
const [isHidden, setIsHidden] =useState(Array(12).fill(true));
const [icon] = useState(animalArray);
const renderButton = index => {
return (
<Button
icon={icon[index]}
isHidden={isHidden[index]}
onClick={() =>setIsHidden(!isHidden[index])}
/>
);
};
return (
<div className="board">
<div className="container">
<div className="row align-items-start">
<div className="col-3">{renderButton(0)}</div>
<div className="col-3">{renderButton(1)}</div>
<div className="col-3">{renderButton(2)}</div>
So of course I wanted to toggle isHidden state in specific tile after clicking its button. Instead I'm getting every tile flipped on first click, then on following clicks nothing happens. I tried modifying it, like creating new variables, copying isHidden, etc. Thank you.
Upvotes: 2
Views: 111
Reputation: 281686
Since state updater doesn't merge the state you need to pass on the entire updated state to the updater and use callback pattern. You also need to return a new instance of the array instead of modifying it otherwise state uptader wouldn't detect a change and it won't re-render
const renderButton = index => {
return (
<Button
icon={icon[index]}
isHidden={isHidden[index]}
onClick={() =>setIsHidden(prevHidden => Object.assign([], prevHidden, {[index]: !prevHidden[index])}
/>
);
};
Upvotes: 1
Reputation: 1742
The onClick
should be
onClick={() => setIsHidden(
isHidden.map((hidden, hiddenIndex) => (
index === hiddenIndex ? !hidden : hidden
))
)}
Upvotes: 1
Reputation: 23980
<Button
icon={icon[index]}
isHidden={isHidden[index]}
onClick={() =>setIsHidden(!isHidden[index])}
/>
Your state (isHidden
) is an array, but you are updating it to a boolean.
You could do something like:
<Button
icon={icon[index]}
isHidden={isHidden[index]}
onClick={() =>
setIsHidden(oldArray => {
return Object.assign([...oldArray, { [index]: !oldArray[index] }])
})
}
/>
Upvotes: 1