'Does react retain event on subsequent rerenders after assigning it in useEffect?

React says it reregisters event on every rerender on below occasion:

function App() {
  const [count, setCount] = useState(0);
  const registerhandler = (event) => {
    setCount((prev) => prev + 1);
  }

  return (
    <>
      <p>{count}</p>
      <button type="button" id="button1" onClick={registerhandler}>Click</button>
    </>
  )

}

What about the registering event in useEffect, does it retain event between rerenders, or how does it work:

function App() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.getElementById('button1').addEventListener('click', () => {
      setCount((prevCount) => prevCount + 1);
    })
  }, []);
  return (
    <>
      <p>{count}</p>
      <button type="button" id="button1">Click</button>
    </>
  )
}


Solution 1:[1]

The second would apply only 1 callback handler once when the component mounts, but querying the DOM is generally considered anti-pattern in react.

If you want to bind an event handler once then either memoize the callback:

function App() {
  const [count, setCount] = useState(0);

  const registerhandler = useCallback((event) => {
    setCount((prev) => prev + 1);
  }, []);

  return (
    <>
      <p>{count}</p>
      <button type="button" onClick={registerhandler}>
        Click
      </button>
    </>
  );
}

Or use a React ref to access the underlying DOMNode: (don't forget to clean up the effect and remove the listener!)

function App() {
  const [count, setCount] = useState(0);
  const ref = useRef();

  useEffect(() => {
    const buttonRef = ref.current;

    const handler = () => {
      setCount((prevCount) => prevCount + 1);
    };

    buttonRef.addEventListener('click', handler);

    return () => {
      buttonRef.removeEventListener('click', handler);
    };
  }, []);

  return (
    <>
      <p>{count}</p>
      <button ref={ref} type="button">Click</button>
    </>
  )
}

Unless you've an actual performance issue though, just use the first example where the handler is created each render.

function App() {
  const [count, setCount] = useState(0);

  const registerhandler = (event) => {
    setCount((prev) => prev + 1);
  };

  return (
    <>
      <p>{count}</p>
      <button type="button" onClick={registerhandler}>
        Click
      </button>
    </>
  );
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Drew Reese