Accueil / Articles

Création d’un composant de sélection configurable pour React Native Paper

Une présentation détaillée de la conception et du partage sous licence open source de react-native-paper-select, abordant la recherche, les éléments de sélection multiples, les listes structurées et les compromis en termes de performance.

Éditeur : REACTAPP.TOP12 min de lecture2663 mots

Sources: I Built a React Native Select Component — and Turned It Into an Open-Source Package: `react-native-paper-select`

Créer un véritable menu déroulant dans React Native est presque jamais aussi simple qu’il y paraît

Si vous avez passé du temps à essayer d’implémenter un vrai menu déroulant dans React Native, vous savez déjà que « juste un menu déroulant » se transforme rapidement en une tâche bien plus complexe.

Vous devez alors gérer l’état de sélection, intégrer la fonction de recherche, prendre en charge plusieurs sélections, gérer des listes longues, afficher l’interface de manière native sur mobile, ajouter des validations et veiller à ce que l’ensemble s’intègre visuellement au reste de votre application.

Si votre projet est déjà basé sur React Native Paper, utiliser une bibliothèque d’interface distincte uniquement pour obtenir un champ de sélection fonctionnel semble superflu.

C’est précisément ce problème que ce composant a été conçu pour résoudre.

L’objectif était de créer un composant de sélection réutilisable qui s’intégrerait naturellement dans React Native Paper, fonctionnant tant pour une sélection unique que multiple, et permettant à chaque projet d’éviter de reconstruire sans cesse le même modèle d’interaction.

Ainsi, il a été développé de zéro.

Ce qui a commencé comme un composant UI assez restreint est finalement devenu react-native-paper-select — un package open source pour React Native qui inclut désormais la recherche, la sélection multiple, une affichage basé sur des fiches, des listes segmentées, la sélection par boutons radio, des panneaux en bas de l’écran, des menus, ainsi qu’un affichage de listes optimisé pour les performances.

Cet article aborde la motivation derrière sa création, l’évolution du composant au fil du temps, les choix techniques qui l’ont façonné, ainsi que les leçons apprises en transformant un outil initialement conçu pour une seule application en une bibliothèque open source polyvalente.

Le problème

En apparence, les listes déroulantes semblent simples.

Cependant, une fois que l’on commence réellement à les implémenter, de nombreuses questions de conception se posent :

  • Comment afficher la valeur actuellement sélectionnée ?
  • Le champ doit-il permettre une seule sélection ou plusieurs ?
  • Quelle est la meilleure présentation pour la liste des choix ?
  • Comment fonctionnera la recherche au sein de cette liste ?
  • Le comportement doit-il différer entre Android et iOS ?
  • Comment afficher des listes très longues sans nuire aux performances ?
  • Comment garder l’API destinée aux développeurs simple ?
  • Comment permettre des personnalisations sans rendre le composant trop complexe à utiliser ?

Résoudre ces problèmes depuis zéro dans chaque application individuelle n’avait pas de sens.

Au lieu de créer un autre composant unique spécifique à une application, il était plus judicieux de concevoir dès le départ quelque chose qui puisse être réutilisé.

L’idée de base était simple :

Créer un composant de sélection basé sur les primitives UI fournies par React Native Paper, et le rendre suffisamment pratique pour que d’autres développeurs React Native aient envie de l’utiliser.

Présentation de react-native-paper-select

react-native-paper-select est un composant configurable pour React Native qui prend en charge à la fois les cas d’usage de sélection unique et multiple.

La première version s’appuyait sur des éléments de base déjà disponibles dans React Native Paper, notamment :

  • TextInput
  • Checkbox
  • Dialog

L’objectif était de fournir aux développeurs une expérience de sélection visuellement et comportementalement cohérente avec les applications déjà conçues en utilisant le système de design de React Native Paper.

Au fur et à mesure que le package s’est développé, il est passé au-delà de cette première implémentation pour prendre en charge des styles de présentation supplémentaires ainsi que des comportements de sélection plus avancés.

Installation du package

Il ne faut que quelques étapes pour commencer à l’utiliser.

npm install react-native-paper-select

Ou, si vous préférez Yarn :

yarn add react-native-paper-select

Une fois installé, importez le composant de la manière suivante :

import { PaperSelect } from 'react-native-paper-select';

Un Select de base

Pour créer un champ select minimal, il vous suffit d’une liste d’options et d’une fonction pour gérer la sélection.

Voici un exemple :

const [selected, setSelected] = useState({
  value: '',
  label: '',
});
const options = [
  {
    _id: '1',
    value: 'React Native',
  },
  {
    _id: '2',
    value: 'Flutter',
  },
  {
    _id: '3',
    value: 'Native Android',
  },
];

Puis affichez le composant :

<PaperSelect
  label="Framework"
  value={selected.label}
  onSelection={(value) => setSelected(value)}
  arrayList={options}
  selectedArrayList={selected}
/>

Ce qui importe ici, ce n’est pas la brièveté du code, mais plutôt ce que ce code cache.

D’un point de vue de l’application, il n’y a en réalité que deux questions à répondre :

Quelles options sont disponibles ?

et

Quelle option a été choisie par l’utilisateur ?

Tout ce qui concerne la présentation et l’interaction est géré en interne par le composant lui-même.

Sélection unique vs Sélection multiple

Prendre en charge à partir du début à la fois la sélection unique et la sélection multiple était l’un des critères essentiels pour ce composant.

La sélection unique est assez simple à comprendre :

Select Framework
----------------
○ React Native
○ Flutter
○ Native Android

Cependant, la sélection multiple implique une gestion d’état supplémentaire :

Select Technologies
-------------------
☑ React Native
☑ TypeScript
☐ Flutter
☑ Node.js

Cela signifie que le composant doit s’occuper de :

  1. Suivre l’état de sélection
  2. Gérer le désélectionnement
  3. Afficher plusieurs valeurs sélectionnées en même temps
  4. Renvoyer l’ensemble mis à jour des sélections
  • Mettre l’interface affichée en synchronisation avec les données sous-jacentes
  • L’objectif était de contenir toute cette complexité au sein même du composant, plutôt que de la transférer à chaque développeur utilisant le package.

    Pourquoi React Native Paper ?

    Puisque l’application existante reposait déjà sur React Native Paper, il était naturel de développer le composant select en s’appuyant sur ce même système de conception.

    Au lieu de réinventer chaque élément visuel, le composant pouvait réutiliser les éléments d’interface déjà fournis par Paper.

    À un niveau général, la structure interne ressemblait à peu près à ceci :

                    PaperSelect
                         │
              ┌──────────┴──────────┐
              │                     │
          TextInput            Selection UI
                                    │
                        ┌───────────┼───────────┐
                        │           │           │
                     Checkbox      Radio       List
    

    Ce choix de conception apporte un réel avantage.

    Toute application utilisant déjà React Native Paper peut intégrer ce composant select sans introduire un style visuel qui entrerait en conflit avec le reste de l’interface.

    De la boîte de dialogue à plusieurs styles de présentation

    La première version du composant ne proposait qu’un dialogue pour effectuer une sélection.

    L’interaction fonctionnait de la manière suivante :

    TextInput
        ↓
    User taps field
        ↓
    Dialog opens
        ↓
    User selects an item
        ↓
    Selected value appears in TextInput
    

    Cependant, à mesure que le composant se développait, il est devenu évident qu’un dialogue n’était pas toujours le modèle adapté à chaque écran mobile.

    Les besoins en termes d’UX varient beaucoup d’une application à l’autre.

    Afin de tenir compte de cela, le composant a été étendu pour prendre en charge plusieurs modes d’affichage :

    • Dialogue
    • Fenêtre en bas de l’écran
    • Menu

    Avec ce changement, le même composant de sélection peut être intégré dans des contextes d’interaction très différents, et les développeurs n’ont pas besoin de réécrire leur intégration pour passer d’un mode à l’autre.

    Par exemple :

    <PaperSelect
      presentationStyle="bottomSheet"
      ...
    />
    

    Ce degré de flexibilité a représenté un progrès significatif pour la bibliothèque.

    La logique de sélection reste identique quel que soit le style choisi — seul le mode de présentation à l’utilisateur change.

    Gestion de listes longues

    Un défi moins évident avec les composants de type menu déroulant est la performance de la liste à mesure qu’elle s’allonge.

    Imaginez un composant de sélection contenant :

    10 items
    

    C’est très simple à afficher.

    Imaginez maintenant en contenant :

    1,000 items
    

    ou même :

    10,000 items
    

    Afficher autant d’éléments de liste en même temps peut commencer à nuire à la réactivité d’une application mobile.

    Pour éviter cela, le package fait appel à FlashList pour afficher ses listes d’options.

    Le principe est simple :

    Large dataset
          ↓
    Virtualized list
          ↓
    Render what is needed
          ↓
    Better scrolling performance
    

    La performance n’est pas un problème que l’on peut reporter jusqu’à ce que l’on développe quelque chose à grande échelle.

    Tout composant destiné à être réutilisé doit être conçu dès le départ en tenant compte de l’échelle, car il est rarement possible de savoir à l’avance quelle sera la taille des ensembles de données qui lui seront transmis.

    Recherche

    Au fur et à mesure que le nombre d’options sélectionnables augmente, la recherche devient essentielle.

    Au lieu de faire défiler les utilisateurs indéfiniment à travers une longue liste, le composant offre un moyen de recherche pour réduire le choix.

    Le flux est le suivant :

    Search
      ↓
    Filter options
      ↓
    Select result
      ↓
    Update selection
    

    Cela peut sembler un ajout mineur du point de vue de l’utilisateur, mais il a un impact considérable sur l’ergonomie une fois que l’ensemble de données dépasse quelques éléments seulement.

    Sélection multiple avec des icônes

    Afficher plusieurs valeurs sélectionnées en même temps peut rapidement rendre l’interface encombrée.

    Par exemple, une valeur telle que :

    React Native, TypeScript, Node.js, MongoDB
    

    est difficile à interpréter lorsqu’elle est insérée dans un champ de texte standard.

    Les icônes résolvent ce problème.

    Les valeurs sélectionnées peuvent également être affichées sous forme de blocs séparés et distincts :

    [ React Native ] [ TypeScript ]
    [ Node.js ]      [ MongoDB ]
    

    Le composant prend en charge cet affichage basé sur des puces pour les scénarios de sélection multiple, offrant aux utilisateurs une vision beaucoup plus claire de ce qu’ils ont choisi.

    Cela rend également la suppression des sélections individuelles bien plus intuitive.

    Listes par sections

    Un autre critère soulevé était la possibilité de regrouper des options liées entre elles.

    Au lieu d’une longue liste plate comme :

    React
    Angular
    Vue
    Node.js
    Java
    Python
    MongoDB
    PostgreSQL
    

    les options peuvent être organisées sous des titres :

    Frontend
    
    ☐ React
    ☐ Angular
    ☐ Vue
    Backend☐ Node.js
    ☐ Java
    ☐ Python
    Database☐ MongoDB
    ☐ PostgreSQL
    

    Ce regroupement facilite grandement la consultation et la compréhension de grands ensembles d’options.

    Dans le mode de sélection multiple, permettre aux utilisateurs de sélectionner toute une section d’un seul coup accélère considérablement le processus.

    Par exemple :

    ☑ Frontend
    
        ☑ React
        ☑ Angular
        ☑ Vue
    

    Cela vaut mieux que de forcer quelqu’un à tapoter chaque élément un par un.

    Boutons radio pour une sélection unique

    Les cases à cocher sont utiles lorsque plusieurs options peuvent être choisies.

    Cependant, dans les scénarios de sélection unique, les boutons radio communiquent plus clairement l’intention à l’utilisateur.

    C’est pourquoi le package propose également une version basée sur des boutons radio pour l’interface de sélection.

    L’idée fondamentale reste la même :

    Options
       ↓
    User chooses one
       ↓
    Selection state updated
    

    Seule la présentation visuelle change.

    Cela souligne un principe important pour la création de composants réutilisables :

    Gardez la logique de sélection séparée de sa présentation.

    TypeScript et conception d’API

    Puisque cet outil est destiné à être utilisé par d’autres développeurs, la structure de l’API est tout aussi importante que l’apparence de l’interface.

    Quelqu’un qui utilise le package ne doit pas avoir besoin de connaître son fonctionnement interne.

    Input
      ↓
    Options
      ↓
    User interaction
      ↓
    Selection
      ↓
    Callback
    

    plutôt que :

    Dialog state
    Modal state
    List state
    Search state
    Checkbox state
    Rendering state
    ...
    

    Une API de composant bien conçue cache cette complexité interne au consommateur.

    C’est l’une des leçons les plus claires issues de la création et de l’amélioration continue de ce package.

    Le logiciel open source change la manière dont on construit

    Rédiger un composant pour son propre application est une tâche différente de celle consistant à en créer un destiné à un public plus large de développeurs.

    Dans le cadre d’une seule application, l’objectif peut être :

    « Cela résout mon cas spécifique. »

    Lorsque le projet devient open source, la question change pour devenir :

    « Cette API aurait-elle du sens pour un développeur qui n’a jamais vu le code source ? »

    Ce changement modifie vos priorités pendant le développement.

    Soudain, vous prêtez beaucoup plus d’attention à des éléments tels que :

    • La cohérence dans toute l’API
    • La documentation
    • La compatibilité vers l’arrière
    • Les cas limites
    • Des valeurs par défaut sensées
    • Les définitions de types
    • Les options de personnalisation
    • La performance
    • Le versionnement

    Ce qui commence comme un composant petit et simple peut devenir quelque chose de surprenamment complexe une fois que d’autres développeurs commencent à s’en servir en production.

    Comment le projet a évolué avec le temps

    Ce qui était au départ un composant de sélection simple s’est progressivement transformé en un ensemble d’outils de sélection plus complet.

    On peut approximativement reconstituer son évolution de la manière suivante :

    Simple Select
          ↓
    Single Selection
          ↓
    Multi Selection
          ↓
        Search
          ↓
    Large List Handling
          ↓
        Chips
          ↓
       Sections
          ↓
    Radio Selection
          ↓
    Bottom Sheet
          ↓
    Menu Presentation
    

    Chaque nouvelle fonctionnalité répondait à un véritable problème lié à l’ergonomie ou à l’expérience des développeurs.

    C’est l’un des aspects qui se distinguent dans le développement ouvert.

    Lorsque vous lancez la version 1, il est rare d’avoir une vision claire de l’aspect final de la bibliothèque achevée.

    Au lieu de cela, le package continue d’évoluer au fur et à mesure que des exigences réelles, des retours utilisateurs et de nouveaux cas d’usage apparaissent.

    Leçons tirées du processus

    1. De petits problèmes peuvent devenir des projets open source utiles

    Le problème initial n’était en rien révolutionnaire.

    Il manquait simplement un composant select réutilisable.

    Cependant, il existe une véritable différence entre corriger quelque chose pour son propre usage et le perfectionner au point où d’autres personnes puissent également l’utiliser.

    Parfois, cette différence est suffisamment importante pour justifier le lancement d’un projet open source.

    2. Rendre quelque chose réutilisable signifie l’abstraire correctement

    Un composant bien conçu ne devrait pas être lié de manière étroite à l’application spécifique qui l’a vu naître.

    À la place, il doit présenter une interface propre et simple à l’extérieur tout en cachant sa complexité interne.

    Ce principe s’applique bien au-delà du monde de React Native.

    3. La conception des composants concerne également l’expérience utilisateur

    Rendre un composant réutilisable au niveau du code n’est pas tout.

    La manière dont l’utilisateur interagit avec lui est tout aussi importante.

    Les dialogues, les panneaux en bas de l’écran, les menus, les icônes, les champs de recherche, les boutons radio et les listes segmentées ne sont que différentes solutions à la même question fondamentale :

    Quel est le meilleur moyen pour une personne de faire un choix ?

    4. Les composants réutilisables doivent être conçus en tenant compte des performances

    C’est précisément pour cette raison que les décisions concernant l’affichage des listes et la virtualisation doivent être prises dès la phase de conception, et non en dernière minute lorsque des problèmes de performance apparaissent en production.

    5. La documentation fait partie intégrante du package, pas un supplément

    Un code qui fonctionne ne suffit pas pour considérer un package comme terminé.

    Les développeurs ont encore besoin de réponses claires concernant :

    • Comment l’installer
    • Comment l’utiliser
    • Quelles propriétés sont exposées
    • Quelle forme doivent avoir les données attendues
    • Comment personnaliser son comportement et son apparence
    • Quelles fonctionnalités sont réellement prises en charge

    Une documentation solide est ce qui comble l’écart entre quelqu’un qui pense :

    "I found this package."
    

    et le moment où il peut affirmer avec confiance :

    "I can use this package."
    

    La suite du projet

    Le but initial de react-native-paper-select était modeste : un composant de sélection qui s’intégrerait naturellement dans les applications déjà utilisant React Native Paper.

    Depuis, il est devenu un élément bien plus complet, offrant désormais plusieurs modes de sélection, divers styles de présentation, une fonction de recherche, une sélection basée sur des fiches, des données structurées en sections, ainsi qu’un affichage de listes optimisé pour les performances.

    Il reste encore beaucoup de place pour l’améliorer davantage.

    Aucun projet open source n’est jamais vraiment terminé.

    De nouveaux appareils continuent d’apparaître, React Native lui-même publie régulièrement des mises à jour, les attentes en matière de design évoluent, les besoins en accessibilité se transforment, les considérations de performance refont surface, et les développeurs continuent d’envoyer des retours utiles à prendre en compte.

    Cette évolution continue fait partie de ce qui rend la maintenance d’une telle bibliothèque véritablement passionnante.

    Remarques finales

    Travailler sur react-native-paper-select a montré qu’un projet open source n’a pas besoin de partir d’une vision grandiose.

    Souvent, il commence avec un petit problème spécifique que l’on rencontre en développant autre chose.

    On le résout soi-même.

    Puis il devient évident que cette solution peut aider d’autres personnes confrontées au même problème.

    Alors on l’améliore.

    On l’documente correctement.

    On le met à disposition du public.

    Au fil du temps, un petit composant interne peut se transformer en un package sur lequel d’autres développeurs comptent pour leurs propres projets.

    Telle est l’histoire derrière react-native-paper-select.

    Si votre projet utilise React Native Paper et que vous avez besoin d’un composant de sélection flexible ou multi-sélection, le répertoire est hébergé sur GitHub, et le paquet lui-même est publié sur npm.

    Tous les retours, rapports de bugs et contributions sont toujours les bienvenus si vous utilisez ce paquet.