Oskar Nawara
Oskar Nawara

Reputation: 49

Problem with setting value with react hooks

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

Answers (3)

Shubham Khatri
Shubham Khatri

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

Rannie Aguilar Peralta
Rannie Aguilar Peralta

Reputation: 1742

The onClick should be

onClick={() => setIsHidden(
  isHidden.map((hidden, hiddenIndex) => (
    index === hiddenIndex ? !hidden : hidden
  ))
)}

Upvotes: 1

pomber
pomber

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

Related Questions