How to add Event Listeners to UseRefs within UseEffect

4.2k views Asked by At

I want to add an eventListener to a node in my React component. I am selecting the node with a useRef hook. I am useCallback since the useRef is null on it's first render.

const offeringsContainer = useRef(null);

const setOfferingsContainer = useCallback((node) => {
  if (node !== null) {
    offeringsContainer.current = node;
  }
}, []);

My issue is that my useEffect is not reacting to any changes done to the offeringContainer ref. Meaning, offeringContainer.current is null.

useEffect(() => {
    checkHeaderState();
    offeringsContainer.current.addEventListener("wheel", onOfferingsContainerWheel, { passive: false });
}, [offeringsContainer.current]);

This is my JSX:

return (
    <Fragment>
      <div className="card-business-products-services-title-text">
        Products &amp; Services
      </div>
      <div
        className="card-business-products-services-container"
        id="card-business-products-services-container"
        onWheel={onOfferingsContainerWheel}
        ref={setOfferingsContainer}
      >
        {renderOfferings()}
      </div>
    </Fragment>
);

I know I am doing something incorrectly, but my useEffect hook should be listening to any changes from offeringsContainer.current.

1

There are 1 answers

0
Paul Alekseev On BEST ANSWER

You can just past offeringsContainer to the ref of the component. useEffect will be invoked only when there is first rendering that's why your offeringsContainer.current will not be null.

And you forgot to remove listener after the component will be unmounted.

Your code should be like this;

const offeringsContainer = useRef(null);

useEffect(() => {
  checkHeaderState();
  offeringsContainer.current.addEventListener(
    "wheel",
    onOfferingsContainerWheel,
    { passive: false }
  );

  return () => offeringsContainer.current.removeEventListener("wheel");
}, []);

return (
  <Fragment>
    <div className="card-business-products-services-title-text">
      Products &amp; Services
    </div>
    <div
      className="card-business-products-services-container"
      id="card-business-products-services-container"
      onWheel={onOfferingsContainerWheel}
      ref={offeringsContainer}
    >
      {renderOfferings()}
    </div>
  </Fragment>
);

Example: https://codesandbox.io/s/wizardly-banzai-3fhju?file=/src/App.js