Skip to content

Instantly share code, notes, and snippets.

@GeDiez
Created April 19, 2018 19:16
Show Gist options
  • Save GeDiez/62dc5c97893aeb0591f8a6131a72786b to your computer and use it in GitHub Desktop.
Save GeDiez/62dc5c97893aeb0591f8a6131a72786b to your computer and use it in GitHub Desktop.
MAIN FUNCTION: HOC NucleusWrapper @description it HOC lets add custom events to html tags. @Usage you only need to import the HOC as follow: import NucleusWrapper from '../NucleusWrapper' then make a component with: const MiComponent = NucleusWrapper('mi-component') notice: this HOC just receives string tag as parameters. finally you can add you…
/*
MAIN FUCTION: HOC NucleusWrapper
@description
it HOC lets add custom events to html tags.
@usage
you only need to import the HOC as follow:
import NucleusWrapper from '../NucleusWrapper'
then make a component with:
const MiComponent = NucleusWrapper('mi-component')
notice: this HOC just receives string tag as parameters.
finally you can add your events like any React component, for example:
if you has a event named customClick you should add a prop in this way
<MiComponent onCustomClick={() => {}}>text o node of React</MiComponent>
it has two RESTRICTIONS:
1.- your custom event should be pass with "on- prefix and use camelcase
2.- the value of prop should be a function
*/
import React, { Component } from 'react';
import PropTypes from 'prop-types';
/**
* getEvents: receives all props it filter
* regarding restrictions mentioned above
*/
const getEvents = props => {
const keys = Object.keys(props);
if (keys.length === 0) return false;
return keys.reduce((arr, key) => {
const callback = props[key];
const name = key.replace(/^on[A-Z]/, substr =>
substr.slice(-1).toLowerCase()
);
if (!!key.match(/^on[A-Z]/) !== true || typeof callback !== 'function')
return arr;
return [...arr, { name, callback }];
}, []);
};
const bindEventsToElement = (element, events) => {
events.forEach(event => {
element.addEventListener(event.name, event.callback);
});
};
const removeEventsToElement = (element, events) => {
events.forEach(event => {
element.removeEventListener(event.name, event.callback);
});
};
const NucleusWrapper = Tag =>
class extends Component {
static propTypes = {
children: PropTypes.node,
};
static defaultProps = {
children: null,
};
constructor(props) {
super(props);
this.events = getEvents(props);
}
componentDidMount() {
bindEventsToElement(this.tag, this.events);
}
componentWillUnmount() {
removeEventsToElement(this.events);
}
render() {
const { children } = this.props;
return (
<Tag
ref={e => {
this.tag = e;
}}
{...this.props}
>
{children}
</Tag>
);
}
};
export default NucleusWrapper;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment