React Custom Hooks: useEventListener
Tags: react, tutorial, webdev
Published: 2019-09-25 05:59:20

---
title: React Custom Hooks: useEventListener
published: true
description: This custom hook takes care of setting up the event listener on a component mount and removing the listener on component unmount.
tags: react, tutorial, webdev
cover_image: https://thepracticaldev.s3.amazonaws.com/i/id3u9he524ogx2iugql4.jpeg
---

This is a really simple and straightforward, but also a really useful custom hook. This custom React hook takes care of setting up the event listener on a component mount and removing the listener on component unmount.

## addEventListener and removeEventListener

Let's take a look at the `addEventListener` and `removeEventListener` function definitions so we can see what parameters we need to pass to the custom hook in order to make it flexible for all use-cases.

```js
target.addEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, options]);
```

From the definitions, we can see that both functions use the following parameters: `target`,`type`, `listener` and `options`. Now that we've established the input parameters, we can go ahead and create our hook.


## Custom hook


```js
import { useEffect } from 'react';

const useEventListener = (target, type, listener, ...options) => {
  React.useEffect(
    () => {
      target.addEventListener(type, listener, ...options);
      return () => {
        target.removeEventListener(type, listener, ...options);
      };
    },
    [target, type, listener, options]
  );
};
```

We use `useEffect` React hook to take care of what is happening on component mount and unmount. If you want to know more about `useEffect` hook, I've covered it in detail here:

{% link https://dev.to/prototyp/react-useeffect-explained-with-lifecycle-methods-296n %}

This is how we initiate our hook in another component (for example, we are listening to window resize event).

```js
useEventListener(window, 'resize', handleWindowResize);
```

This hook works well if we pass a `document` or `window` or object. If that's going to be the use case for our custom hook, then we can leave it as it is. However, if we intend to pass refs, this custom hook will need some small modifications in order to also work with refs.

### Adding ref functionality

```js
import { useEffect } from 'react';

const useEventListener = (target, type, listener, ...options) => {
  React.useEffect(
    () => {
      const targetIsRef = target.hasOwnProperty("current");
      const currentTarget = targetIsRef ? target.current : target;
      if (currentTarget)
        currentTarget.addEventListener(type, listener, ...options);
      return () => {
        if (currentTarget)
          currentTarget.removeEventListener(type, listener, ...options);
      };
    },
    [target, type, listener, options]
  );
};
```

Inside the `useEffect` hook, we are checking if the passed target is a ref or a `window` or a `document` element.

This is how we are initializing our hook (we can initialize as many listeners as we need in the same component):

```js
// Window resize listener
useEventListener(window, 'resize', handleWindowResize);

// You can also pass refs
const elementRef = useRef(null);
useEventListener(elementRef, 'mousedown', handleElementClick);
```

## Codepen example
{% codepen https://codepen.io/AdrianBece/pen/pozGGdE %}


<hr />


Thank you for taking the time to read this post. If you've found this useful, please give it a ❤️ or 🦄, share and comment.