Armen Nersisyan
Armen Nersisyan

Reputation: 333

How to add Event in React Functional Component

I have a question about React functional components, specifically about functions in functional components. For instance:

import React, { useEffect } from 'react';

const Component = (props) => {  
  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
  });
  useEffect(() => {
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  function handleScroll() {
    let scrollTop = window.scrollY;
  }


  return ()
}

Upvotes: 12

Views: 33019

Answers (3)

Damien Flury
Damien Flury

Reputation: 778

You should add and remove the eventlistener in the same useEffect-call. For instance:

import React, { useEffect } from 'react';

const Component = (props) => {

  useEffect(() => {
    function handleScroll() {
      const scrollTop = window.scrollY;
      console.log(scrollTop);
    }

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    <div />
  );
}

Upvotes: 10

junwen-k
junwen-k

Reputation: 3644

This is just a quick demo on how to use useEffect to subscribe to event, useRef to create element ref for event listener, and useState to store the event results.

Please note that this is for the sake of demonstration purpose only. Calling setState in every tick of scroll event callback is NOT ideal.

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

const App = () => {
  // set default value
  const [scrollTop, setScrollTop] = useState(document.body.scrollTop);

  // create element ref
  const innerRef = useRef(null);

  useEffect(() => {
    const div = innerRef.current;
    // subscribe event
    div.addEventListener("scroll", handleOnScroll);
    return () => {
      // unsubscribe event
      div.removeEventListener("scroll", handleOnScroll);
    };
  }, []);

  const handleOnScroll = (e) => {
    // NOTE: This is for the sake of demonstration purpose only.
    // Doing this will greatly affect performance.
    setScrollTop(e.target.scrollTop);
  }

  return (
    <>
      {`ScrollTop: ${scrollTop}`}
      <div
        style={{
          overflow: 'auto',
          width: 500,
          height: 500,
          border: '1px solid black',
        }}
        ref={innerRef}
      >
        <div style={{ height: 1500, width: 1500 }}>
          Scroll Me
        </div>
      </div>
    </>
  )
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Here is a working demo in code sandbox: https://codesandbox.io/s/react-functional-component-event-listener-demo-fmerz?fontsize=14

Upvotes: 18

Armen Nersisyan
Armen Nersisyan

Reputation: 333

import React, { useEffect } from 'react';

const Component = (props) => {  
  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
  });
  useEffect(() => {
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  function handleScroll() {
    let scrollTop = window.scrollY;
  }


  return ()
}

Upvotes: -3

Related Questions