skip to Main Content

I have a button that shows/hides an element when click but it does not work on first click but it works on the following clicks. I’m expecting it to work on the first click.

import { useState } from "react";

function myComponent() {

    const [elem, setElem] = useState(false);
    const handleClick = () => {
        setElem(true);
        if(elem) {
            document.getElementById('item').classList.toggle('show');
            document.getElementById('item').classList.toggle('hide');
        }
    }

    return (
        <button onClick={handleClick}>touch me</button>
    );
}

export default Navbar;

What I imagine that is happening under the hood is that when the button is clicked it will set the elem to ‘true’ then the ‘if’ statement runs because the elem is ‘true’. I also tried to console.log the elem outside and inside the if statement and it shows false and the if statement doesn’t run on the first click. I could just remove the if statement and not use a State but I want to do other things if the button is clicked. Can someone explain to me what really is happening here under the hood? Thank you!

2

Answers


  1. setElem() does not immediately mutate elem but creates a pending state transition. Accessing elem after calling this method can potentially return the existing value.

    You can use useEffect hook.

    import { useState, useEffect } from "react";
        
        function myComponent() {
        
            const [elem, setElem] = useState(false);
            const handleClick = () => {
                setElem(true);
               
            }
        
        useEffect(()=>{
         if(elem) {
                 document.getElementById('item').classList.toggle('show');
                 document.getElementById('item').classList.toggle('hide');
         }
        },[elem])
        
            return (
                <button onClick={handleClick}>touch me</button>
            );
        }
        
        export default Navbar;
    
    Login or Signup to reply.
  2. setState calls in React are asynchronous. That means that after you call setElem(true), elem hasn’t updated yet when the if statement runs and is therefore still false.

    Instead, you can set the state after you run the if statement like so:

    const handleClick = () => {
        if(!elem) {
            document.getElementById('item').classList.toggle('show');
            document.getElementById('item').classList.toggle('hide');
        }
        setElem(true);
    }
    

    Alternatively, you could use setElem with a callback or the useEffect hook.

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