skip to Main Content

I am new in React and face an issue.

I have several divs and when a div is clicked, I want to add a new class in this div only.

The issue is when I click on a class, it adds a new class in this div, but it also adds new classes in all other divs.

Please take a look at my code below and please give me a hand.

Thanks

export default function Toggle() {
  const [hoverToggle, setHoverToggle] = useState();
  const toggleIt = () => {
    setHoverToggle(!hoverToggle);
  };
return (
<>
      <div
        onClick={toggleIt}
        className={`${hoverToggle ? "getClick" : "noClick"}`}
      >
        This is DIV 1
      </div>
      <div
        onClick={toggleIt}
        className={`${hoverToggle ? "getClick" : "noClick"}`}
      >
        This is DIV 2 
      </div>
      <div
        onClick={toggleIt}
        className={`${hoverToggle ? "getClick" : "noClick"}`}
      >
        This is DIV 3
      </div>
</>
)

3

Answers


  1. Your variable hoverToggle is shared with all divs.
    Maybe try this :

    export default function ParentComponent() {
      const divs = [1, 2, 3];
    
      function displayDiv(divNumber) {
        const [hoverToggle, setHoverToggle] = useState();
        const toggleIt = () => {
          setHoverToggle(!hoverToggle);
        };
    
        return (
          <div onClick={toggleIt} className={`${hoverToggle ? 'getClick' : 'noClick'}`}>
            This is DIV {divNumber}
          </div>
        );
      }
    
      return <>{divs.map((divNumber) => displayDiv(divNumber))}</>;
    }
    

    This way each created div will have its separate state.

    Login or Signup to reply.
  2. The reason why new classes are being added to all other divs is that you are using the same useState() and toggleIt function for all the divs. Whenever a click occurs in any of the divs, the toggleIt function gets called, which causes a change in the hoverToggle. Since you are only using one hoverToggle for the three divs, this change affects all of them. I hope this explanation is clear enough.

    Try this out, I believe it will work out fine.

       export default function Toggle() {
          const [hoverToggleDiv1, setHoverToggleDiv1] = useState();
          const [hoverToggleDiv2, setHoverToggleDiv2] = useState();
          const [hoverToggleDiv3, setHoverToggleDiv3] = useState();
        
          const toggleItDiv1 = () => {
            setHoverToggleDiv1(!hoverToggleDiv1);
          };
          const toggleItDiv2 = () => {
            setHoverToggleDiv2(!hoverToggleDiv2);
          };
          const toggleItDiv3 = () => {
            setHoverToggleDiv3(!hoverToggleDiv3);
          };
        
          return (
            <>
              <div
                onClick={toggleItDiv1}
                className={`${hoverToggleDiv1 ? "getClick" : "noClick"}`}
              >
                This is DIV 1
              </div>
              <div
                onClick={toggleItDiv2}
                className={`${hoverToggleDiv2 ? "getClick" : "noClick"}`}
              >
                This is DIV 2
              </div>
              <div
                onClick={toggleItDiv3}
                className={`${hoverToggleDiv3 ? "getClick" : "noClick"}`}
              >
                This is DIV 3
              </div>
            </>
          );
        }
    
    Login or Signup to reply.
  3. As the same state is used in all three div elements, regardless of which one is clicked, the CSS class is applied to all of them.

    Instead of using a boolean value for the state, you can use a numeric value to target only the clicked element.

    export default function Toggle() {
      const [hoverToggle, setHoverToggle] = useState(null);
    
      const toggleIt = (n) => {
        setHoverToggle(n !== hoverToggle ? n : null)
      }
    
      return (
        <>
          {[1, 2, 3].map(index =>
            <div
              key={index}
              onClick={() => toggleIt(index)}
              className={hoverToggle === index ? 'getClick' : 'noClick'}
            >
              This is DIV {index}
            </div>
          )}
        </>
      )
    }
    

    This should give you the toggle behavior you are looking for. The getClick class is added if the value of hoverToggle matches the index of the clicked element, otherwise it is replaced by the noClick class.

    Also note that when an item is clicked twice in a row, the state is reset to its initial value of null to create the toggle effect.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search