EN
React - useEvent() hook
7 points
In this short article, we would like to show how in React, create custom event listener hook that cleans up event automatically when component is removed.
Quick solution:
xxxxxxxxxx
1
import {useRef, useEffect} from 'react';
2
3
const useEvent = (object, event, callback) => {
4
const ref = useRef(null);
5
useEffect(
6
() => {
7
const wrapper = (e) => {
8
if (ref.current) {
9
ref.current(e);
10
}
11
};
12
object.addEventListener(event, wrapper);
13
return () => object.removeEventListener(event, wrapper);
14
},
15
[object, event]
16
);
17
ref.current = callback;
18
};
19
20
21
// Usage example (put it into component):
22
23
useEvent(window, 'click', (e) => { /* ... */ });
Where:
object
argument indicates object for what we want to add event,event
argument indicates event name that we want to listen,
e.g.click
,mousedown
,mouseup
,keydown
,keyup
, etc.,callback
argument indicates function that is called when event occurs on the object.
In the below example we monitor 3 cases:
- when key is down,
- when key is up,
- and when window losts focus (
blur
event).
Source code:
xxxxxxxxxx
1
// import React from 'react';
2
// import ReactDOM from 'react-dom';
3
4
const useEvent = (object, event, callback) => {
5
const ref = React.useRef(null);
6
React.useEffect(
7
() => {
8
const wrapper = (e) => {
9
if (ref.current) {
10
ref.current(e);
11
}
12
};
13
object.addEventListener(event, wrapper);
14
return () => object.removeEventListener(event, wrapper);
15
},
16
[object, event]
17
);
18
ref.current = callback;
19
};
20
21
22
// Usage example:
23
24
const App = () => {
25
const [key, setKey] = React.useState(null);
26
useEvent(window, 'keydown', (e) => setKey(e.key));
27
useEvent(window, 'keyup', (e) => setKey(null));
28
useEvent(window, 'blur', (e) => setKey(null));
29
return (
30
<div>
31
<div>Click on this text to get focus and press some key on the keyboard!</div>
32
<div>
33
<span>Pessed key: </span>
34
<span>{key ?? '[UNDEFIEND]'}</span>
35
</div>
36
</div>
37
);
38
};
39
40
const root = document.querySelector('#root');
41
ReactDOM.render(<App />, root );