Preface
In the development of React, we often need to register some events on the window, such as pressing Esc to close the pop-up window, pressing up and down keys to select the list content, etc. A common operation is to listen to an event on the window when the component is mounted and stop listening to the event when the component is unmount ed. Next, I'd like to introduce a few operations.
WindowEventHandler
We create a WindowEventHandler component as follows
import PropTypes from 'prop-types'; import { Component, PureComponent } from 'react'; export default class WindowEventHandler extends (PureComponent || Component) { static propTypes = { eventName: PropTypes.string.isRequired, callback: PropTypes.func.isRequired, useCapture: PropTypes.bool, }; static defaultProps = { useCapture: false, }; componentDidMount() { const { eventName, callback, useCapture } = this.props; window.addEventListener(eventName, callback, useCapture); } componentWillUnmount() { const { eventName, callback, useCapture } = this.props; window.removeEventListener(eventName, callback, useCapture); } render() { return null; } }
Now, for example, if we want to listen to the resize event of window in component A, we can write this in component A
export default class A extends (PureComponent || Component) { handleResize = () => { // dosomething... } render() { return ( <div> //I am component A <WindowEventHandler eventName="resize" callback= /> </div> ); } }
In this way, we don't need to write hook functions of mount and unmount in multiple components, which saves a lot of things.
Using decorators
We can write a unified decorator for the component. As before, we can pass in the event name and method name to listen, and stop listening when the component is uninstalled. The code is as follows
export default function windowEventDecorator(eventName, fn) { return function decorator(Component) { return (...args) => { const inst = new Component(...args); const instComponentDidMount = inst.componentDidMount ? inst.componentDidMount.bind(inst) : undefined; const instComponentWillUnmount = inst.instComponentWillUnmount ? inst.componentWillUnmount.bind(inst) : undefined; const callback = (e) => { typeof inst[fn] === 'function' && inst[fn](); }; inst.componentDidMount = () => { instComponentDidMount && instComponentDidMount(); document.body.addEventListener(eventName, callback, true); }; inst.componentWillUnmount = () => { instComponentWillUnmount && instComponentWillUnmount(); document.body.removeEventListener(eventName, callback, true); }; return inst; }; }; }
Similar to such A decorator, similarly, we want to listen to the resize event of window in A, which can be written as follows
@windowEventDecorator('resize', 'handleResize'); export default class A extends (PureComponent || Component) { handleResize = () => { // dosomething... } render() { return ( <div> //I am component A </div> ); } }
summary
This kind of small skill improves the development efficiency, writes a lot of code less, may try in the project code.