Isaac Medina
Isaac Medina

Reputation: 332

How to add Event Listeners to UseRefs within UseEffect

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.

Upvotes: 0

Views: 4770

Answers (1)

Pavel Alekseev
Pavel Alekseev

Reputation: 1222

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

Upvotes: 2

Related Questions