En Qumulo, ayudamos a nuestros clientes a comprender su capacidad de almacenamiento y rendimiento mediante el análisis interactivo. Mejoramos continuamente nuestra analítica; escuchamos lo que nuestros clientes necesitan, rastreamos los eventos correctos en el sistema y luego brindamos nuevas funciones de interfaz de usuario para organizar e interactuar de forma inteligente con estos datos. Y enviamos estas nuevas características cada dos semanas.
Enviar una nueva interfaz de usuario web cada dos semanas significa que no podemos dejar que nuestras herramientas se interpongan en nuestro camino. Adoptamos nueva tecnología cuando nos ayuda a ir más rápido y escribir mejor código. Cuando empezamos en 2012, usamos plantillas de Backbone, jQuery y Underscore. Tres años más tarde, todos tratamos sobre React, D3.js, ES2015 y Babel, con un cambio de los modelos Backbone mutables hacia una arquitectura de flujo de datos unidireccional de Flux. Ser capaz de evolucionar nuestro código base de manera incremental es fundamental para el envío regular, ya que no podemos detener y reescribir nuestra aplicación web utilizando las últimas tecnologías.
Tecnología genial: React + D3.js
Por sí solos, React y D3 son excelentes bibliotecas de JavaScript. Sin embargo, lograr que trabajen bien juntos puede ser un desafío. Intentamos varios enfoques de diseño diferentes en los últimos dos años, y finalmente hemos encontrado un enfoque de diseño que aprovecha las fortalezas de cada biblioteca.
Entonces, ¿qué tiene de difícil usar React con D3? El problema está en lograr que las bibliotecas cooperen en la representación de elementos en la pantalla de una manera que le permita usar toda la potencia de cada biblioteca. Comencemos con un ejemplo de un componente React que es responsable de representar un gráfico de líneas. Esta fue la primera iteración de nuestra función de Historial de capacidad, que muestra cuánto espacio de almacenamiento de clúster se ha utilizado a lo largo del tiempo:
En este ejemplo simple, tenemos un eje X de tiempo, un eje Y de capacidad y un gráfico lineal. Podríamos factorizar esto en cuatro componentes de React: un componente de gráfico principal que administra datos para tres componentes secundarios:
let CapacityHistoryGraph = React.createClass ({render () {return ( ); }});
Siempre que el accesorio graphData cambie en el componente padre, React llamará a la función render () de CapacityHistoryGraph, que enviará nuevos accesorios a los hijos. Aquí hay un enfoque común que verá recomendado para construir un componente React que envuelva D3, usando LineChart como ejemplo:
let LineChart = React.createClass ({render () {return ; ) componendDidMount () {// React renderizó el elemento, deje que D3 represente el resto this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;}); this.renderLineChart (this.props.data); } shouldComponentUpdate (nextProps) {// Deje que D3 actualice el gráfico, pero evite que React vuelva a renderizar this.renderLineChart (nextProps.data); falso retorno; } renderLineChart (datos) {d3.select (this.refs.lineChart) .removeAll () .append ("ruta") .attr ("d", this.line (datos)); }});
Técnicamente, esto funciona; el gráfico de líneas se renderizará y actualizará cuando cambien los accesorios. Es un poco confuso, porque está luchando contra el ciclo de vida predeterminado de React al suprimir la representación después del primer procesamiento (consulte la declaración resaltada "devolver falso"). Y a medida que genere más componentes React + D3, si alguno de ellos necesita generar componentes React secundarios, no podrá enviarles cambios de propiedades porque nunca volverán a procesarse. La capacidad de composición de los componentes es un principio clave de React, y no queríamos renunciar a eso.
Un mejor enfoque
Después de crear suficientes componentes y experimentar con diferentes enfoques, nos dimos cuenta de que hay una manera de aprovechar las mejores partes de cada marco sin renunciar a las características. Primero, declaremos nuestras metas:
- Los componentes de React deben ser compostables para su máxima reutilización.
- Por lo tanto, los componentes de React deben rendir y enviar accesorios a sus hijos.
- D3 es responsable de los cálculos (como averiguar dónde dibujar puntos según la escala y la ventana) durante el renderizado
- Los componentes de React incluyen elementos DOM basados en cálculos D3 como parte del render siempre que sea posible
Entonces, ¿cómo arreglamos el ejemplo de LineChart de arriba para cumplir con estos objetivos? En lugar de dejar que D3 cree el y asignarle puntos, dejamos que React renderice el y deje que D3 complete la lista de puntos durante el render.
let LineChart = React.createClass ({componentWillMount () {this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;} );} render () {return ( ); )});
Como resultado, observe cómo el código del componente LineChart es mucho más limpio y fácil de leer. Las cosas son un poco más complicadas para el componente del eje de tiempo porque queremos que D3 calcule la escala de tiempo, el número de marcas de graduación que se mostrarán y dónde mostrarlas. d3.svg.axis hace todo este trabajo por nosotros, pero necesita un elemento DOM existente para renderizar. Por lo tanto, necesitamos usar los ganchos del ciclo de vida componentDidMount / componentDidUpdate de React para agregar elementos al DOM después de que React haga su pase de renderizado.
let LineChart = React.createClass ({componentWillMount () {this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;} );} render () {return ( ); )});
Este enfoque ha funcionado bien para nosotros. Un resumen rápido:
- Siempre deje que los componentes React se procesen.
- Crea elementos SVG en render yourselfv
- Aproveche D3 para cálculos y para generar elementos SVG cuando sea necesario
Con eso, nuestros componentes React basados en D3 son fácilmente reutilizables en diferentes contextos de visualización, y escribir nuevos componentes es sencillo. Encontrar una solución como esta requirió experimentación y tiempo para ver qué funcionaría mejor. Todo eso es parte de cómo creamos software de forma incremental en Qumulo.
Pruebe Qumulo gratis
Explore un entorno Qumulo completamente funcional, directamente en su navegador.
Prueba Demo