skip to Main Content

I am new to React, so apologies about the probably simple question.

Assume I have the following code:

const myComponent = () => {

    const [someVar, setSomeVar] = useState(0);

    // Other code

    useEffect(() => {
    
        // Do something
    
    }, [someVar]);

        
    return (
        <button>Hello</button>
    )
}

Everything is great so far, and whenever someVar changes useEffect runs.

Now, is it possible to do the following?

const myComponent = () => {

    const [someVar, setSomeVar] = useState(0);

    // Other code

    useEffect(() => {
    
        // Do something
    
    }, [<button with ID helloButton clicked>]);  // <--------- this is what I want

        
    return (
        <button
            id="helloButton"
            onClick={() => {
                // Do on click related stuff
            }}
        >
            Hello
        </button>
    )
}

As you can see in the pseudo-code above, I want useEffect to be triggered by detecting the user clicked the button that has ID helloButton

Is this possible?

3

Answers


  1. Well, the most obvious solution to me is that you move the content of the useEffect to a function and call this function on click:

    const MyComponent = () => {
      const [someVar, setSomeVar] = useState(0);
    
      const myFunc = useCallback(() => {
        // Do on click related stuff
      }, [/*...*/])
    
      useEffect(myFunc, [myFunc]);
    
      return (
        <button
          id="helloButton"
          onClick={myFunc}
        >
          Hello
        </button>
      )
    }
    

    Now, if for some reason you don’t want to do that, you can also use a state that you will change on click, and pass it in the dependency array of your useEffect. For example:

    const MyComponent = () => {
      const [someVar, setSomeVar] = useState(0);
      const [triggerEffect, setTriggerEffect] = useState(Date.now());
    
      useEffect(() => {
        // Do something
      }, [triggerEffect]);
    
      return (
        <button
          id="helloButton"
          onClick={() => {
            setTriggerEffect(Date.now());
            // Do on click related stuff
          }}
        >
          Hello
        </button>
      )
    }
    
    Login or Signup to reply.
  2. This looks like a use case for the useCallback hook

    const myComponent = () => {
      const [someVar, setSomeVar] = useState(0);
    
      // Other code
    
      const handleOnClick = useCallback(() => {
          // Do something
      }, []);
    
      return (
          <button
              id="helloButton"
              onClick={handleOnClick}
          >
              Hello
          </button>
      );
    };
    
    Login or Signup to reply.
  3. Something like the following snippet?

    In short, it gets the element id from e.target.id and sets it to state.
    Inside of the useEffect we conditionally check if the id from state is equal to the element id and if this condition is truthy we then trigger the call there.
    When the component will unmount return () => {} we set the value again to 0 to avoid infinite loops.

    There are many ways to achieve the same, for instance, using the useRef hook. It can vary depending of the case.

    I hope it makes sense.

    You can play around if you will codesandbox-io

    import "./styles.css";
    import { useEffect, useState } from "react";
    
    const MyComponent = () => {
      const [someVar, setSomeVar] = useState(0);
    
      useEffect(() => {
        if (someVar === "helloButton") {
          // example
          window.alert(someVar);
        }
        return () => {
          setSomeVar(0);
        };
      }, [someVar]);
    
      return (
        <>
          <button
            id="helloButton"
            onClick={({ target }) => {
              setSomeVar(target.id);
            }}
          >
            Hello
          </button>
          <button
            id="button"
            onClick={({ target }) => {
              setSomeVar(target.id);
            }}
          >
            Good bye
          </button>
        </>
      );
    };
    
    export default MyComponent;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search