Header Ads Widget

Ticker

6/recent/ticker-posts

Portar una biblioteca JS a un componente React

 


La publicación de invitado de Kloudless ayuda a mejorar la interoperabilidad de React

Con el reciente crecimiento de las tecnologías front-end, React se ha convertido en uno de los marcos más populares. También hemos visto que la interoperabilidad entre estos marcos se ha convertido en una alta prioridad, especialmente cuando se incluye JavaScript vanilla .

Por lo tanto, es fundamental que las organizaciones se centren en la interoperabilidad para los desarrolladores de React. En este artículo, presentamos cómo portar una biblioteca JS a un componente React reutilizable , así como a un Componente de orden superior (HOC). También cubrimos cualquier obstáculo que encontramos en el camino y ofrecemos consejos útiles sobre cómo lo resolvimos.

Hemos simplificado el código de ejemplo en este artículo en aras de la legibilidad. También puede visitar la página de GitHub para obtener el código de muestra completo.

Una breve introducción a las bibliotecas JS

La mayoría de las bibliotecas de JavaScript vanilla se incluyen mediante una <script>etiqueta en algún lugar del HTML, ya sea en el encabezado o en la parte inferior de la página. A menudo, la biblioteca de JavaScript funciona como un widget que un usuario lanzará en la página.

En este ejemplo, la biblioteca JS del Explorador de archivos lanza un widget de interfaz de usuario que permite a los usuarios buscar y seleccionar archivos y carpetas de los servicios de almacenamiento en la nube .

Configuramos esta biblioteca JS creando una instancia del explorador con opciones de configuración. Esta biblioteca JS expone un choose()método y se puede llamar mediante programación para iniciar el widget JS.

const options = {
  app_id: 
};
const explorer = window.Kloudless.explorer(options);
buttonElement.onclick = function() {
  // call this method whenever you want to launch Chooser
  explorer.choose();
};

Empecemos

Elegimos usar React 15 para este proyecto porque era la versión más estable en el momento del desarrollo. Sin embargo, React hace un muy buen trabajo al mantener versiones estables y compatibilidad con versiones anteriores.

Como desarrollador, no queremos reescribir toda la biblioteca JS ya que las funcionalidades seguirán siendo utilizadas por los usuarios y clientes existentes. Por lo tanto, elegimos agregar un contenedor React y simplemente reutilizar el código JS central.

Muchas bibliotecas vanilla JS dependen de la interacción y la entrada del usuario; por lo tanto, necesitamos React para renderizar un botón para mantener la misma funcionalidad. Incluimos esto mediante el uso del evento del ciclo de vida componentDidMount()y vinculamos un controlador de eventos de clic al botón. Ahora, podemos llamar a métodos JS expuestos como choose()para iniciar el widget JS cada vez que se hace clic en el botón.

Además, podemos usar componentWillReceiveProps()para reinicializar la instancia de la biblioteca JS para asegurarnos de que los cambios en los accesorios se propaguen.

Dado que React y otros marcos ya no se importan desde una etiqueta de script en el HTML, exponemos la biblioteca JS con una variable global para importar la biblioteca JS como un módulo ES6.

class Chooser extends React.Component {
  constructor(props) {
    super(props);
    this.explorer = null;
    this.onClick = this.onClick.bind(this);
  }
  componentDidMount() {
    // initialize explorer
    this.explorer = window.Kloudless.explorer(this.props.options);
  }
  componentWillReceiveProps(nextProps) {
    // re-initialize the explorer when options changing
    if (nextProps.options !== this.props.options) {
      this.explorer = window.Kloudless.explorer(nextProps.options);
    }
  }
  onClick() {
    // call choose() to launch the Chooser
    this.explorer.choose();
  }
  render() {
    return ;
  }
}

¡Hasta aquí todo bien! Sin embargo, algunas bibliotecas JS usan iframes para personalizar la apariencia del widget JS. En este caso, notamos un problema con los iframes y una posible pérdida de memoria.

Cuando se trabaja con widgets JS, sumergirse en el código fuente es una necesidad al realizar la migración a React. A veces, aún se requieren modificaciones menores a la biblioteca JS.

var initialize_frame = function (options, elementId) {
  var frame = document.createElement('iframe');
  // configure frame
  var body = document.getElementsByTagName("body")[0];
  if (elementId) {
    var el = document.getElementById(elementId);
    el.appendChild(frame);
  } else {
    body.appendChild(frame);
  }
}
 
Kloudless.explorer = function (options) {
  initialize_frame(...);
}

Necesitamos un mecanismo de limpieza para eliminar el iframe agregando un método destroy () a la biblioteca JS.

Kloudless.explorer.destroy = function () {
frame.parentNode.removeChild(frame); };

Luego podemos llamar destroy()para eliminar correctamente el iframe.

  • componentWillReceiveProps(): llamadas antes de que se inicialice el nuevo explorador.
  • componentWillUnmount(): llama antes de que el componente se desmonte

El código final de React es el siguiente:

class Chooser extends React.Component {
  constructor(props) {
    super(props);
    this.explorer = null;
    this.onClick = this.onClick.bind(this);
  }
  componentDidMount() {
    // initialize explorer
    this.explorer = window.Kloudless.explorer(this.props.options);
  }
  componentWillReceiveProps(nextProps) {
    // re-initialize the explorer when options changing
    if (nextProps.options !== this.props.options) {
      this.explorer.destroy();
      this.explorer = window.Kloudless.explorer(nextProps.options);
    }
  }
  componentWillUnmount() {
    this.explorer.destroy();
  }
  onClick() {
    // call choose() to launch the Chooser
    this.explorer.choose();
  }
  render() {
    return ;
  }
}

Avanzado: componente de orden superior

Aunque este componente de React es utilizable, queremos simplificar todo el proceso y modificar la menor cantidad de código posible. Para los desarrolladores que ya han implementado sus propios componentes de botón, un componente de orden superior (HOC) puede ser una forma más fácil de mejorar sus componentes para manejar eventos de usuario. Esto también evitará tener que reescribir toda la lógica del componente.

La mayoría de los desarrolladores de React probablemente hayan usado un HOC antes, como el de Redux connect()Es esencialmente una función que toma un componente y lo envuelve en un nuevo componente. (Consulte la documentación de React para obtener más detalles). Al agregar soporte para un HOC, los desarrolladores pueden transformar sus componentes personalizados en un componente de biblioteca JS más fácilmente.

// create chooser component
const chooser = createChooser(customComponent);
 
// usage

Nuestro HOC debe cumplir con los siguientes requisitos:

  • Agregue una capa transparente sobre el componente envuelto para administrar la instancia de la biblioteca JS.
  • No debería afectar el uso original del componente envuelto. Es decir, además de los accesorios especificados de la biblioteca JS, todos los demás accesorios deben pasar por alto el componente envuelto. Además, los métodos estáticos del componente envuelto deben copiarse en el nuevo componente.
  • Necesitamos piratear el controlador de eventos de clic para llamar choose().
  • Si el componente empaquetado no tiene un controlador de eventos de clic o su nombre no lo tiene onClick, solo asegúrese de que el método se llame correctamente en el componente empaquetado. Por ejemplo, cuando se hace clic en el botón.
    El createChoosercódigo HOC final es el siguiente:
 
import hoistNonReactStatics from 'hoist-non-react-statics';
 
const createChooser = (WrappedComponent) => {
  class Wrapper extends React.Component {
    constructor(props) {
      super(props);
      this.explorer = null;
      this.onWrappedCompClick = this.onWrappedCompClick.bind(this);
    }
    componentDidMount() {
      const { options } = this.props;
      this.explorer = window.Kloudless.explorer(options);
    }
    componentWillReceiveProps(nextProps) {
      const { options } = this.props;
      if (nextProps.options !== options) {
        this.explorer.destroy();
        this.explorer = window.Kloudless.explorer(options);
      }
    }
    componentWillUnmount() {
      this.explorer.destroy();
    }
    onWrappedCompClick(...args) {
      const { onClick = () => { } } = this.props;
      onClick(...args);
      this.explorer.choose();
    }
    render() {
      // do not pass options and event handler to the wrapped component
      const { options, onClick, ...restProps } = this.props;
      return (
        
      );
    }
  }
 
  // set display name for easy debugging
  Wrapper.displayName = (`createChooser(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`);
 
  // use hoist-non-react-statics to copy non-react static methods
  hoistNonReactStatics(Wrapper, WrappedComponent);
 
  return Wrapper;
};

Conclusión

En este artículo, cubrimos cómo portamos nuestra biblioteca JS, el Explorador de archivos, a un componente React reutilizable. También hemos proporcionado una opción para envolver su componente personalizado en un componente de orden superior. De reaccionar métodos de ciclo de vida hacen que el proceso de portar una biblioteca JS reaccionar mucho más fácil mediante el uso de componentDidMountcomponentWillUnmountcomponentWillReceivePropsUna nota final es tener cuidado con los efectos secundarios, como la manipulación de variables globales, detectores de eventos o el árbol DOM. Asegúrese de que funcionen independientemente de varios componentes y asegúrese de que los componentes se limpien al desmontarlos. Siga estos consejos y no debería tener problemas para migrar sus propias bibliotecas.

Publicar un comentario

0 Comentarios