Ingénierie Front-End chez Qumulo : React + D3.js

Chez Qumulo, nous aidons nos clients à comprendre leur capacité de stockage et leurs performances en fournissant des analyses interactives. Nous améliorons continuellement nos analyses. Nous écoutons ce dont nos clients ont besoin, nous suivons les bons événements dans le système, puis nous livrons de nouvelles fonctionnalités d'interface utilisateur pour organiser et interagir intelligemment avec ces données. Et nous expédions ces nouvelles fonctionnalités toutes les deux semaines.

En envoyant une nouvelle interface Web toutes les deux semaines, nous ne pouvons pas laisser nos outils nous gêner. Nous adoptons de nouvelles technologies chaque fois que cela nous aide à aller plus vite et à écrire un meilleur code. Lorsque nous avons commencé dans 2012, nous avons utilisé des modèles Backbone, jQuery et Underscore. Trois ans plus tard, nous parlons de React, D3.js, ES2015 et Babel, avec un décalage des modèles Backbone mutables vers une architecture de flux de données unidirectionnelle Flux. Être capable de faire évoluer notre base de code de manière incrémentale est essentiel pour la livraison régulière, car nous ne pouvons pas arrêter et réécrire notre application Web en utilisant les dernières technologies.

Cool tech: React + D3.js

React et D3 sont des bibliothèques JavaScript excellentes. Cependant, les amener à bien travailler ensemble peut constituer un défi. Nous avons essayé plusieurs approches de conception différentes au cours des deux dernières années et avons finalement trouvé une approche de conception qui exploite les atouts de chaque bibliothèque.

Alors, comment utiliser React avec D3? Le problème est de faire en sorte que les bibliothèques coopèrent pour rendre les éléments à l’écran d’une manière qui vous permet d’utiliser toute la puissance de chaque bibliothèque. Commençons par un exemple d'un composant React chargé de rendre un graphique en courbes. Il s’agissait de la toute première itération de notre fonctionnalité Historique de capacité, qui indique la quantité d’espace de stockage de cluster utilisée au fil du temps:

Dans cet exemple simple, nous avons un axe X temporel, un axe Y de capacité et un graphique linéaire. Nous pourrions le factoriser en quatre composants React - un composant graphique parent qui gère les données de trois composants enfants:

let CapacityHistoryGraph = React.createClass ({render () {return ( ); }});

Chaque fois que l'accessoire graphData change sur le composant parent, React appellera la fonction render () de CapacityHistoryGraph, qui enverra de nouveaux accessoires aux enfants. Voici une approche courante recommandée pour la création d'un composant React englobant D3, en utilisant le graphique LineChart comme exemple:

let LineChart = React.createClass ({render () {return ; ) componentDidMount () {// React a rendu le élément, laissez D3 rendre le reste this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;}); this.renderLineChart (this.props.data); } shouldComponentUpdate (nextProps) {// Laisser D3 mettre à jour le graphique, mais empêcher React de restituer this.renderLineChart (nextProps.data); retourner faux; } renderLineChart (données) {d3.select (this.refs.lineChart) .removeAll () .append ("chemin") .attr ("d", this.line (données)); }});

Techniquement, cela fonctionne; le graphique en courbes sera rendu et mis à jour lorsque les accessoires changent. C'est kludgy, parce que vous combattez le cycle de vie par défaut de React en supprimant le rendu après le premier rendu (voir la déclaration "return false" en surbrillance). Et comme vous construisez plus de composants React + D3, si l'un d'entre eux a besoin de rendre des composants enfants React, vous ne pouvez pas leur envoyer de changements de prop car ils ne seront jamais rendus. La composition des composants est un principe clé de React, et nous ne voulions pas y renoncer.

Une meilleure approche

Après avoir créé suffisamment de composants et expérimenté différentes approches, nous avons réalisé qu'il existe un moyen de tirer parti des meilleurs composants de chaque infrastructure sans renoncer aux fonctionnalités. Premièrement, énonçons nos objectifs:

  1. Les composants de réaction doivent être composables pour une réutilisation maximale
  2. Les composants de réaction doivent donc rendre et transmettre les accessoires à leurs enfants
  3. D3 est responsable des calculs (comme déterminer où dessiner des points en fonction de l'échelle et de la fenêtre d'affichage) pendant le rendu.
  4. Les composants React incluent des éléments DOM basés sur des calculs D3 dans le cadre du rendu lorsque cela est possible

Alors, comment corriger l'exemple LineChart ci-dessus pour atteindre ces objectifs? Au lieu de laisser D3 créer le et lui attribuer des points, nous laissons React rendre le , et laissez D3 remplir la liste des points pendant le rendu.

let LineChart = React.createClass ({componentWillMount () {this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;} );} render () {return ( ); )});

En conséquence, regardez comment le code du composant LineChart est beaucoup plus propre et plus facile à lire! Les choses sont un peu plus compliquées pour le composant de l'axe des temps car nous voulons que D3 calcule l'échelle de temps, le nombre de graduations à afficher et où les afficher. d3.svg.axis fait tout ce travail pour nous, mais il a besoin d'un élément DOM existant pour le rendu. Par conséquent, nous devons utiliser les hooks de cycle de vie componentDidMount / componentDidUpdate de React pour ajouter des éléments au DOM après que React ait effectué son rendu.

let LineChart = React.createClass ({componentWillMount () {this.line = d3.svg.line () .x ((d) => {return dx;}) .y ((d) => {return dy;} );} render () {return ( ); )});

Cette approche a bien fonctionné pour nous. Un résumé rapide:

  • Toujours laisser les composants React rendre
  • Créer des éléments SVG dans render nous-même
  • Exploitez D3 pour les calculs et pour générer des éléments SVG si nécessaire

Avec cela, nos composants React basés sur D3 sont facilement réutilisables dans différents contextes d'affichage, et l'écriture de nouveaux composants est simple. Trouver une solution comme celle-ci nécessitait de l'expérimentation et du temps pour voir ce qui fonctionnerait le mieux. Tout cela fait partie de la façon dont nous construisons progressivement des logiciels chez Qumulo.

Testez gratuitement Qumulo

Testez gratuitement Qumulo

Explorez un environnement Qumulo entièrement fonctionnel, directement dans votre navigateur.

Try Demo

Partager cette publication