Passer au contenu principal

Native Base Picker : Configuration, Styling & Correction Android

Implémentez le Native Base Picker dans React Native. Cette guide couvre la configuration, l'état, la mise en forme et une correction critique pour le bug de la fonctionnalité onValueChange sur Android.

Native Base Picker : Configuration, Styling & Correction Android

Vous avez probablement rencontré le même mur que de nombreux équipes de React Native avec le NativeBase Picker. Le menu déroulant s'affiche, il ressemble à ce qu'il doit être, iOS fonctionne, et puis Android ignore votre logique. Pas de crash. Pas de warning. Juste un sélecteur qui semble fonctionnel tout en ignorant votre logique métier. onValueChange Content Marketer

Pourquoi le NativeBase Picker continue de surprendre les développeurs expérimentés. La mise en place est simple, la mise en forme est gérable, mais la fiabilité en production dépend de la compréhension d'une erreur Android spécifique que la plupart des guides ignorent ou n'évoquent jamais.

Table des matières

Démarrage avec le sélectionneur NativeBase

Un sélectionneur est généralement l'un de ces composants que vous ajoutez tard dans un sprint. Sélecteur de pays, champ de statut, type de rendez-vous, option de livraison. Il a l'air petit jusqu'à ce que le comportement de la plateforme commence à se refléter dans votre interface.

La bonne nouvelle est que le Sélectionneur NativeBase est facile à obtenir sur l'écran. Il a été conçu pour afficher un sélecteur natif sur iOS et Android et pour remplacer le sélecteur React Native obsolète dans les anciens ensembles NativeBase, ce qui est la raison pour laquelle de nombreux codebases de legacy dépendent encore de lui.

Un environnement de travail pour les développeurs, avec un ordinateur portable affichant React Native code à côté d'une interface d'application mobile.

Installez le composant dans un setup React Native normal

Si votre projet utilise déjà NativeBase, la principale tâche est d'importer les primitives appropriées et d'éviter la logique de wrapper inutile dès le début. Commencez par le sélecteur de base le plus simple possible.

Si vous travaillez sur plusieurs stacks mobiles et hybrides, cela vous aide également à comprendre comment React code est emballé dans des environnements plus larges comme Les flux de travail d'applications mobiles React avec Capacitor. Le sélecteur code reste familier, mais les attentes de déploiement changent.

Un exemple de base ressemble à ceci:

import React, { useState } from 'react';
import { Container, Content, Form, Item, Picker, Icon } from 'native-base';

export default function BasicPickerScreen() {
  const [selectedValue, setSelectedValue] = useState('key0');

  return (
    <Container>
      <Content padder>
        <Form>
          <Item picker>
            <Picker
              mode="dropdown"
              iosIcon={<Icon name="arrow-down" />}
              selectedValue={selectedValue}
              onValueChange={(value) => setSelectedValue(value)}
            >
              <Picker.Item label="Choose one" value="key0" />
              <Picker.Item label="JavaScript" value="js" />
              <Picker.Item label="TypeScript" value="ts" />
              <Picker.Item label="React Native" value="rn" />
            </Picker>
          </Item>
        </Form>
      </Content>
    </Container>
  );
}

Affichez un premier sélecteur sans abstraction supplémentaire

Cette première passe devrait répondre seulement à deux questions:

  • Est-ce qu'il s'affiche correctement: Vous voulez vérifier que le champ apparait dans votre disposition, respecte l'espace et s'ouvre sur les deux plateformes.
  • Est-ce que votre chemin d'importation est correct : Les projets NativeBase échouent souvent pour des raisons banales telles que la combinaison d'API de composants anciens et nouveaux.
  • Est la valeur sélectionnée contrôlée : Même dans un prototype jetable, utilisez selectedValue à partir de l'état. Le sélecteur non contrôlé code devient plus difficile à déboguer ultérieurement.

Règle pratique : N'entamez pas par la mise en correspondance des données du serveur, des règles de remplissage, des appels d'hooks d'analytique et de validation dans le même sélecteur. Faites d'abord le composant visible et contrôlé.

Cette base minimale compte. Lorsque Android commence à se comporter de manière anormale ultérieurement, vous saurez que le problème n'est pas votre architecture de formulaire entière. C'est le sélecteur.

Liaison de l'état et gestion des sélections

Lorsque le sélecteur s'affiche, le prochain travail consiste à le rendre utile. Dans React Native, cela signifie traiter le sélecteur comme un champ de saisie contrôlé et conserver la valeur sélectionnée dans l'état du composant.

La voie standard est simple. Vous stockez la valeur actuelle avec useStateet la passez dans selectedValue, et mettez à jour cet état à l'intérieur onValueChangeCe même état d'esprit que vous utilisez pour d'autres champs de formulaire comme les modèles de saisie de texte React Nativemême si le contrôle de l'interface utilisateur est différent.

Utilisez une valeur contrôlée dès le début

Voici la version propre que je choisirais avant d'ajouter des validations ou des effets secondaires :

import React, { useState } from 'react';
import { Text } from 'react-native';
import { Form, Item, Picker } from 'native-base';

export default function RolePicker() {
  const [role, setRole] = useState('');

  return (
    <>
      <Form>
        <Item picker>
          <Picker
            mode="dropdown"
            selectedValue={role}
            onValueChange={(value) => setRole(value)}
          >
            <Picker.Item label="Select a role" value="" />
            <Picker.Item label="Admin" value="admin" />
            <Picker.Item label="Editor" value="editor" />
            <Picker.Item label="Viewer" value="viewer" />
          </Picker>
        </Item>
      </Form>

      <Text>Selected role: {role || 'none'}</Text>
    </>
  );
}

Cet code vous donne une source de vérité prévisible. L'interface utilisateur reflète role, et chaque fonction en aval lit dans le même état.

Conservez la logique de sélection simple et testable

Les problèmes commencent généralement lorsque les développeurs surchargent onValueChange. Ils récupèrent des données, mutent plusieurs tranches d'état, déclenchent la navigation et enregistrent des analytics en une seule fonction inline. Lorsque le comportement du sélecteur faille, le débogage devient douloureux.

Un modèle plus approprié est de séparer la stockage de la valeur des effets secondaires :

import React, { useEffect, useState } from 'react';
import { Text } from 'react-native';
import { Form, Item, Picker } from 'native-base';

export default function DepartmentPicker() {
  const [department, setDepartment] = useState('');
  const [message, setMessage] = useState('No department selected');

  useEffect(() => {
    if (!department) {
      setMessage('No department selected');
      return;
    }

    setMessage(`Department selected: ${department}`);
  }, [department]);

  return (
    <>
      <Form>
        <Item picker>
          <Picker
            selectedValue={department}
            onValueChange={setDepartment}
          >
            <Picker.Item label="Select department" value="" />
            <Picker.Item label="Sales" value="sales" />
            <Picker.Item label="Support" value="support" />
            <Picker.Item label="Operations" value="operations" />
          </Picker>
        </Item>
      </Form>

      <Text>{message}</Text>
    </>
  );
}

Cette structure réalise deux choses utiles :

  1. Elle fait en sorte que le sélecteur soit responsable uniquement de l'état de sélection.
  2. Elle déplace le comportement de l'application dans useEffectoù vous pouvez tester et raisonner à son sujet de manière independante.

Si un composant de formulaire ne peut pas vous dire avec certitude quel est la valeur sélectionnée, tous les effets secondaires attachés à lui deviennent suspects.

Ce point devient critique sur Android, où le flux d'événements prévu du sélecteur NativeBase ne tient pas toujours.

Dépannage du Bug de changement de valeur Android

C'est là où la plupart des articles passent à côté. Le sélecteur NativeBase peut paraître en bonne santé sur Android tout en échouant au moment précis où il doit faire du travail.

La documentation communautaire autour de l'ancienne mise en œuvre du sélecteur décrit une véritable scission entre les plateformes. Android ne déclenche pas les fonctions personnalisées attachées à onValueChangealors que iOS le faitet ce dysfonctionnement est décrit comme un 100% de disparité fonctionnelle sur Android avec un taux de réussite de 0% pour le déclenchement des fonctions sur les appareils Android malgré une mise en œuvre identique code Dans les rapports documentés. La même documentation indique aux développeurs des solutions de contournement ou des migrations, et note que le composant NativeBase 3.0 Select atteint 98% de succès dans le déclenchement des fonctions sur les deux plateformes dans les environnements testés en comparaison, comme décrit dans la documentation et le contexte de migration de NativeBase picker.

Un infographique détaillant un bug commun dans le composant NativeBase Picker sur Android et sa solution proposée.

Qu'est-ce qui brise réellement sur Android

La raison pratique est le détail d'implémentation. Sur Android, le NativeBase Picker repose sur le spinner natif, et ce niveau ne propage pas les écouteurs d'événements vers le wrapper comme le font de nombreux développeurs. Sur iOS, le comportement basé sur le modèle se lie correctement au système d'événements.

C'est pourquoi ce bug ressemble à un piège. Vous voyez l'interface utilisateur. Vous pouvez ouvrir les options. Vous pouvez même sélectionner un élément visible. Mais votre fonction métier ne s'exécute jamais.

Un modèle de défaillance typique ressemble à ceci :

<Picker
  selectedValue={status}
  onValueChange={(value) => {
    setStatus(value);
    saveStatusToApi(value);
    trackSelection(value);
    updateDependentFields(value);
  }}
>

Sur iOS, cela peut se comporter exactement comme prévu. Sur Android, le sélecteur peut s'afficher tout en ne déclenchant jamais ces fonctions.

Aide de substitution qui tient la route en production

La solution de substitution la plus fiable est architecturale, pas cosmétique. Gardez l'interaction du sélecteur centrée sur la mise en mémoire d'une valeur sélectionnée, puis réagissez aux changements d'état en dehors du gestionnaire de sélecteur.

import React, { useEffect, useState } from 'react';
import { Form, Item, Picker } from 'native-base';

export default function StatusPicker() {
  const [status, setStatus] = useState('');
  const [didMount, setDidMount] = useState(false);

  useEffect(() => {
    if (!didMount) {
      setDidMount(true);
      return;
    }

    if (!status) return;

    runStatusSideEffects(status);
  }, [status, didMount]);

  const runStatusSideEffects = (value) => {
    console.log('Selected status:', value);
    // call validation, API sync, or dependent form updates here
  };

  return (
    <Form>
      <Item picker>
        <Picker
          selectedValue={status}
          onValueChange={setStatus}
        >
          <Picker.Item label="Select status" value="" />
          <Picker.Item label="Pending" value="pending" />
          <Picker.Item label="Approved" value="approved" />
          <Picker.Item label="Rejected" value="rejected" />
        </Picker>
      </Item>
    </Form>
  );
}

Pourquoi cela aide :

  • L'état reste central : Votre logique de composant surveille status, et non la charge de l'événement de sélecteur seule.
  • Les effets secondaires deviennent explicites : Les appels à API, les mises à jour des champs dépendants et la traçabilité ne vivent plus à l'intérieur d'un appel de callback UI fragile.
  • Le code est plus facile à remplacer ultérieurement : Si vous migrez vers un sélecteur non NativeBase, la plupart de la logique commerciale survit inchangée.

Pour les projets axés sur Android, je recommande également de tester sur un appareil réel tôt, surtout si votre application a déjà une complexité de packaging native comme La mise en place d'Android pour les applications Capacitor.

When la migration vers Select est la décision plus propre

Si le sélecteur se trouve dans un flux critique tel que le paiement, l'inscription ou l'entrée de données réglementées, il peut ne pas être utile de contourner le comportement ancien. À ce stade, passer à NativeBase 3.0 Select est généralement la décision à long terme la plus sûre.

Le bug n'est pas juste un inconvénient. Il change l'emplacement où vous pouvez placer logique commerciale de manière sûre.

Si vous maintenez l'ancien sélecteur, traitez-le comme un coquille de l'interface utilisateur avec une responsabilité minimale. Cette mentalité prévient de nombreux régressions silencieux Android.

Styliser et personnaliser votre composant de sélecteur

Un sélecteur fonctionnel ressemble encore à un produit inachevé s'il ne correspond pas au reste de l'application. NativeBase vous donne suffisamment de crochets pour rendre le contrôle délibéré, mais les résultats les plus propres proviennent généralement de la personnalisation du conteneur autour du sélecteur plutôt que de lutter contre le contrôle natif directement.

Une main tenant un smartphone affichant une application de réservation de voyage avec un menu de sélecteur de base native.

Personnalisez le conteneur avant de personnaliser le sélecteur

Le sélecteur lui-même est en partie contraint par la rendu natif. Le conteneur vous donne un contrôle bien plus grand sur l'espace, le traitement des bordures et le rythme de la disposition.

Un modèle pratique :

import React, { useState } from 'react';
import { StyleSheet } from 'react-native';
import { Form, Item, Picker, Icon } from 'native-base';

export default function StyledPicker() {
  const [country, setCountry] = useState('');

  return (
    <Form>
      <Item style={styles.pickerWrapper} picker>
        <Picker
          mode="dropdown"
          iosIcon={<Icon name="arrow-down" style={styles.icon} />}
          textStyle={styles.pickerText}
          selectedValue={country}
          onValueChange={setCountry}
        >
          <Picker.Item label="Select country" value="" />
          <Picker.Item label="Germany" value="de" />
          <Picker.Item label="Japan" value="jp" />
          <Picker.Item label="Brazil" value="br" />
        </Picker>
      </Item>
    </Form>
  );
}

const styles = StyleSheet.create({
  pickerWrapper: {
    borderWidth: 1,
    borderColor: '#D1D5DB',
    borderRadius: 10,
    marginTop: 12,
    paddingLeft: 8,
    backgroundColor: '#FFFFFF',
  },
  pickerText: {
    color: '#111827',
    fontSize: 16,
  },
  icon: {
    color: '#111827',
    fontSize: 18,
  },
});

Cette approche vous obtient généralement la plupart de la voie sans sur-engineérer les surcharges de thème.

Utilisez une présentation conforme au système d'exploitation

Les systèmes iOS et Android ont rarement besoin d'une mise en forme identique. Ils ont besoin d'une intention cohérente. Le même jeton visuel peut toujours nécessiter des espacements différents, une mise en page d'icône ou un mode de sélection différent.

Les ajustements utiles incluent :

  • Sur iOS : Accordez du souffle au champ et prenez en compte la présentation modale par rapport aux étiquettes entourantes.
  • Sur Android : Vérifiez la mise en page de texte et la hauteur de défaut du spinner sur plusieurs appareils.
  • Pour les deux : Conservez le texte de remplissage visuellement distinct des sélections réelles.

Une comparaison courte aide :

Préoccupation iOS Android
Comportement d'ouverture Sentiment modal Sentiment de chargement
Attentes d'icône Souvent plus décoratif Souvent plus fonctionnel
Problèmes de mise en page La disposition du champ de remplissage peut paraître floue Le texte peut paraître serré

Si votre interface comprend des dégradés, des cartes superposées ou des surfaces à contraste élevé, alignez le conteneur du sélecteur avec le même traitement que vous utilisez ailleurs dans l'interface, tout comme les modèles utilisés dans le travail de dégradé linéaire de React Native __CAPGO_KEEP_0__.

Note de conception : Les utilisateurs jugent un sélecteur moins par le menu déroulant lui-même et plus par la façon dont le champ fermé s'insère dans le formulaire.

C'est pourquoi le rayon de rondeur, l'écartement des étiquettes et la couleur de la zone de texte sont plus importants que les personnalisations exotiques du sélecteur.

Scénarios avancés et meilleures pratiques

La plupart des bugs de sélecteur se manifestent après la phase de prototype. Le problème commence lorsque les options proviennent d'un serveur, les règles de validation diffèrent par plateforme, et la zone de texte ne peut pas agir comme une valeur valide.

Un cas d'edge récurrent est particulièrement ennuyeux sur iOS. Les développeurs ont souvent besoin de charger les valeurs du sélecteur à partir d'un serveur tout en empêchant l'entrée de la zone de texte de pouvoir être sélectionnée, mais les matériaux officiels n'abordent pas directement cette voie. La discussion de la communauté souligne quela valeur de la zone de texte peut rester sélectionnable sur iOS ce qui entraîne un comportement incohérent dans les applications réelles, comme le note cette.

discussion de la communauté React Native sur les valeurs de sélecteur chargées à partir d'un serveur et la sélection de la zone de texte

Un diagramme illustrant le processus de flux de données à quatre étapes pour utiliser un sélecteur dynamique dans NativeBase.

Charger les options du sélecteur à partir des données du serveur de manière sécurisée : L’erreur que je vois le plus souvent est de traiter les données récupérées comme immédiatement prêtes pour le sélecteur. Gardez une petite couche de transformation entre votre réponse API et le composant.

import React, { useEffect, useState } from 'react';
import { Form, Item, Picker } from 'native-base';

export default function DynamicCategoryPicker() {
  const [categories, setCategories] = useState([]);
  const [selectedCategory, setSelectedCategory] = useState('');

  useEffect(() => {
    const loadCategories = async () => {
      const response = await fetch('https://example.com/api/categories');
      const data = await response.json();

      const formatted = data.map((item) => ({
        label: item.name,
        value: String(item.id),
      }));

      setCategories(formatted);
    };

    loadCategories();
  }, []);

  return (
    <Form>
      <Item picker>
        <Picker
          selectedValue={selectedCategory}
          onValueChange={setSelectedCategory}
        >
          <Picker.Item label="Select category" value="" />
          {categories.map((item) => (
            <Picker.Item
              key={item.value}
              label={item.label}
              value={item.value}
            />
          ))}
        </Picker>
      </Item>
    </Form>
  );
}

Cette étape de mise en forme vous donne un contrat stable. Votre sélecteur n'a pas besoin de connaître la forme interne du API.

Prévenir la sélection du champ de remplissage sur iOS

La règle la plus sûre est simple. N'abordez pas le champ de remplissage comme une option réelle, même si la bibliothèque de l'interface utilisateur le rend facile à rendre.

Un modèle pratique :

  • Utilisez une valeur de sentinelle vide : Conservez la valeur du champ de remplissage comme '' ou une autre valeur d'application invalide.
  • Valider avant soumission : Rejetez la valeur vide dans la validation de formulaire, pas seulement dans l'interface utilisateur.
  • Désactiver les actions en aval : N'activez pas le bouton de soumission avant qu'une valeur non vide n'existe.

Pour des flux plus stricts, affichez du texte d'aide lorsque le champ de remplissage reste sélectionné :

const isValidSelection = selectedCategory !== '';

Alors, bloquez les boutons d'action ou les appels de API en fonction de cette condition plutôt que de vous fier à la présentation du sélecteur.

Habitudes d'accessibilité et de production

Les sélecteurs passent souvent inaperçus lors des revues d'accessibilité car ils ressemblent à des éléments natifs. Ils ont cependant besoin de marques claires et d'un état prévisible.

Un ou deux habitudes payent rapidement :

  • Ajoutez des étiquettes d'accessibilité : Faites en sorte que le champ soit compréhensible pour les lecteurs d'écran.
  • Tenez les étiquettes explicites : « Pays » est préférable à « Sélectionner ».
  • Testez la restauration de l'état : Réouvrir un formulaire et confirmez que l'élément sélectionné précédemment apparaît correctement.
  • Écrivez des tests unitaires autour de la logique déterminée par la sélection : La logique en dehors de l'interface utilisateur compte le plus, et test de l'unité du comportement React aide à la protection de ces transitions d'état.

Un sélecteur est rarement critique en soi. Les changements d'état qui se cachent derrière lui sont généralement plus importants.

C'est l'esprit qui maintient les formulaires dynamiques stables. Traitez le sélecteur NativeBase comme une surface d'entrée. Mettez les règles réelles dans votre flux d'état, de validation et de soumission.

Conclusion

Le sélecteur NativeBase est toujours utile lorsque vous comprenez où il se brise. La mise en place est simple, la personnalisation est faisable et les listes d'options dérivées du serveur sont gérables. Un piège critique est la gestion des événements Android. Si vous maintenez la logique métier hors des appels de rappel fragiles du sélecteur et la déplacez dans des effets dérivés d'état, le composant devient beaucoup plus prévisible.

Pour les anciens codebases, ce workaround est souvent suffisant. Pour les flux critiques, la migration vers Select est généralement une meilleure investissement. Quoi qu'il en soit, la clé est la même. N'ayez pas confiance dans le sélecteur juste parce qu'il s'affiche.


Si votre équipe développe des applications Capacitor ou Electron et souhaite envoyer des correctifs JavaScript, CSS, copie, configuration et ressources sans attendre la revue de la boutique Capgo est une option à considérer.

Mises à jour en temps réel pour les applications Capacitor

Lorsqu'un bug de la couche web est en ligne, expédiez la correction par le biais de Capgo au lieu d'attendre des jours pour l'approbation de la boutique d'applications. Les utilisateurs reçoivent la mise à jour en arrière-plan tandis que les modifications natives restent dans le chemin de revue normal.

un soutien humain de Martin

Démarrer Maintenant

Dernières actualités de notre Blog

Capgo vous donne les meilleures informations dont vous avez besoin pour créer une application mobile véritablement professionnelle.