Author avatar

Marques Woodson

Event Listeners in React Components

Marques Woodson

  • Jun 12, 2020
  • 5 Min read
  • 308 Views
  • Jun 12, 2020
  • 5 Min read
  • 308 Views
Web Development
Front End Web Development
Client-side Framework
React

Introduction

Listening to events in a vanilla Javascript app might be something you are familiar with. Doing the same event listening in a React app might be a little more confusing. You may ask yourself, "Where do I add the event listener?" or, "When and how do I cancel an event?" This guide will answer those questions.

Adding an Event Listener

You can create an event listener in a React app by using the window.addEventListener method, just like you would in a vanilla Javascript app:

1
2
3
window.addEventListener('keydown', (event) => {
  // ...
});
js

The code snippet above shows you how to add a keydown event listener to the window. The tricky part of this snippet is knowing where to place it. React is a component-based system. All of your pages are just components, and this means when you add an event listener, it's going to need to happen inside of a component. For example, here is a component where you might add a keydown listener:

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';

const App = (props) => {
  window.addEventListener('keydown', (event) => {
    // ...
  });
  return (
    <div className='container'>
      <h1>Welcome to the Keydown Listening Component</h1>
    </div>
  );
};
js

There are a couple of problems with the code above.

  1. You only want the event listener added when the component finishes rendering.
  2. You need to remove the event listener when the component is unmounted.

To solve the first issue you will need to use the useEffect hook. From the React.useEffect documentation:

The function passed to useEffect will run after the render is committed to the screen.

1
2
3
4
5
6
7
8
9
10
11
12
13
const App = (props) => {
  React.useEffect(() => {
    window.addEventListener('keydown', (event) => {
      // ...
    });
  });

  return (
    <div className='container'>
      <h1>Welcome to the Keydown Listening Component</h1>
    </div>
  );
};
js

Now the addEventListener is being called at the correct time, but there is still a problem: the way it is written now will add a new listener on all component changes. This is because you need to tell the useEffect hook to only run when the component first renders. To do this you can simply add an empty dependency array as the second argument of useEffect:

1
2
3
4
5
6
7
8
9
10
11
12
13
const App = (props) => {
  React.useEffect(() => {
    window.addEventListener('keydown', (event) => {
      // ...
    });
  }, []);

  return (
    <div className='container'>
      <h1>Welcome to the Keydown Listening Component</h1>
    </div>
  );
};
js

Passing that dependency array tells the hook to only run the callback code when one of the dependencies changes. By passing an empty array, the useEffect hook will only run a single time. You would want this behavior in this case since you don't want to add a duplicate event listener.

Removing an Event Listener

Now that you've added the event listener to your component, you will also need to know how to remove that listener when the component is no longer mounted. The function for removing an event listener is window.removeEventListener.

1
window.removeEventListener('keydown', handlekeyDown);
js

You'll notice that the second argument to removeEventListener is not an anonymous function, and is instead a variable. This is necessary for identifying what event listener to remove, since technically you can multiple keydown event listeners running at the same time.

Now you just need to call removeEventListener when the component unmounts, but how do you do that in a functional component? There is no componentDidUnmount lifecycle method, but the useEffect hook helps you out with an optional return value in the callback function. You can return a function in the useEffect callback and that function will run when the component unmounts. Here is what your code should look like after successfully removing an event listener:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const App = (props) => {
  const handleKeyDown = (event) => {
    console.log('A key was pressed', event.keyCode);
  };

  React.useEffect(() => {
    window.addEventListener('keydown', handleKeyDown);

    // cleanup this component
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, []);

  return (
    <div className='container'>
      <h1>Welcome to the Keydown Listening Component</h1>
    </div>
  );
};
js

Conclusion

And there you have it. You now know how to add and remove event listeners in a React component. For more information on working with React components check out this guide on hooks. Thanks for reading!

4