Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
attach-events decorator for react
/**
* @decorator
* Attach events to DOM element
*
* @param {Element|Function} elemOrFunc: DOM Element, or a function returns element
* @param {String} events: a list events separated with ','
* @param {String} preventDecorator: prevent decorate when it doesn't need
*
* Usage:
* @attachEvents(window, 'click')
* handleWindowClick(evt) {
* ...
* }
*
* @attachEvents(window, 'resize', IS_MOBILE)
* handleWindowClick(evt) {
* ...
* }
*
* @attachEvents(document, 'mousedown, touchstart')
* handlePointerDown(evt) {
* ...
* }
*
* @attachEvents(function getElem() { return this.refs.elem; }, 'click')
* handleClickOnElem(evt) {
* ...
* }
*/
const noop = () => {};
export function attachEvents(elemOrFunc, events, preventDecorate) {
if (preventDecorate) return function (target, key, descriptor) { return descriptor; };
const eventList = events.split(/\s*,\s*/);
const getElem = typeof elemOrFunc === 'function' ? elemOrFunc : () => elemOrFunc;
return function decorator(proto, method, descriptor) {
const {
componentDidMount = noop,
componentWillUnmount = noop,
} = proto;
const symbolHandler = Symbol(method);
function addListener() {
const elem = getElem.call(this);
const handler = this[symbolHandler] = (...args) => {
descriptor.value.apply(this, args);
};
eventList.forEach((evt) => {
elem.addEventListener(evt, handler);
});
}
function removeListener() {
const elem = getElem.call(this);
eventList.forEach((evt) => {
elem.removeEventListener(evt, this[symbolHandler]);
});
}
// eslint-disable-next-line no-param-reassign
proto.componentDidMount = function componentDidMountWrapped() {
componentDidMount.call(this);
addListener.call(this);
};
// eslint-disable-next-line no-param-reassign
proto.componentWillUnmount = function componentWillUnmountWrapped() {
componentWillUnmount.call(this);
removeListener.call(this);
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.