Makina Blog

Le blog Makina-corpus

Créer un menu natif crossplatform avec React Native


Ou comment gérer les composants natifs par plateforme ?

Nous avons déjà découvert React Native ensemble.

Aujourd'hui on va voir comment développer un menu React Native cross platform pour une application simple qui aura une page home et une page favoris.

Android et IOs ont leurs propres guidelines. C'est pourquoi tous les composants de React Native ne sont pas cross platform. Par exemple sur Android, on utilise DrawerLayoutAndroid pour afficher un menu, alors que sur iOS on aura plutôt tendance à utiliser le composant TabBarIos. C'est parfait car c'est justement le point que nous allons illustrer ici.

Pour ce faire, nous devons simplement créer 2 composants avec le même nom. Seulement l'extension sera différente.

Menu.android.js

import { DrawerLayoutAndroid } from 'react-native';
var Menu = React.createClass({
[...]
render: function() {
  var navigationView = (
    <View style={[styles.layout]}>
      <View style={[styles.header]}>
        <View style={[styles.headerIcon]}>
          <Icon name="md-bulb" size={60} color="#f1c40f" />
        </View>
      </View>
      <Icon.Button style={[styles.menuItem]} name="md-home"  color='#455A64' backgroundColor="#fff" onPress={this.goHome} borderRadius={0}>
        <Text style={[styles.textItem]}>Home</Text>
      </Icon.Button>
      <Icon.Button style={[styles.menuItem]} name="md-star"  color='#455A64' backgroundColor="#fff" onPress={this.goFavoris} borderRadius={0}>
        <Text style={[styles.textItem]}>Starred</Text>
      </Icon.Button>
    </View>
  );
  return (
    <DrawerLayoutAndroid
      ref={'DRAWER_REF'}
      drawerWidth={300}
      drawerPosition={DrawerLayoutAndroid.positions.Left}
      renderNavigationView={() => navigationView}>
      {this.state.currentView == 'home' ? <ReactNativeView paletteStar={this.state.paletteStar} /> : <Starred selectStar={this.selectStar} /> }
    </DrawerLayoutAndroid>
  );
}
})

Menu.ios.js

import { TabBarIOS } from 'react-native';
[...]
var Bulb = React.createClass({
  render: function() {
  return (
    <TabBarIOS
      unselectedTintColor="yellow"
      tintColor="white"
      barTintColor="#34495e"
      >
      <Icon.TabBarItemIOS
        title="Home"
        iconName="ios-home-outline"
        selectedIconName="ios-home"
        selected={this.state.currentView === 'home'}
        onPress={() => {
          this.setState({
            currentView: 'home',
          });
        }}>
        <ReactNativeView ref={'HOME'} paletteStar={this.state.paletteStar}/>
      </Icon.TabBarItemIOS>
      <Icon.TabBarItemIOS
        title="Starred"
        iconName="ios-star-outline"
        selectedIconName="ios-star"
        selected={this.state.currentView === 'favoris'}
        onPress={() => {
          this.setState({
            currentView: 'favoris'
          });
          this.refs['STARRED'].loadStar();
        }}>
        <Starred ref={'STARRED'} selectStar={this.selectStar} />
      </Icon.TabBarItemIOS>
    </TabBarIOS>
  );
}
})

Gràce à ses extensions (ios.js et android.js), React Native saura qu'il doit utiliser Menu.android.js pour la version android et Menu.ios.js pour iOS.

Notre composant affichera donc selon la plateforme un menu 'TabBar' sur ios et un menu 'Slide' pour android, chacun avec leur propre style.

Des comportements différents

Il faudra faire attention, car justement, ce n'est pas les mêmes composants et donc leurs comportements peut varier.

Ici, lors d'un changement d'option de menu deux scénarios se présentent.

DrawerAndroid : Le composant se recréer à chaque appel, ce qui implique qu'il passera toujours dans notre fonction de cycle de vie ComponentDidMount.

TabBarIos : Les composants ne se rechargent pas chaque fois, ils sont directement créer lors du démarrage de l'application. On ne passera donc pas dans le cycle ComponentDidMount à chaque appel.

Deux choix s'offrent donc à nous, avoir ici aussi un composant home et favoris pour chaque plateforme, ou bien prendre en charge directement dans le composant parent l'action à réaliser lors du changement d'option.

Seulement, l'un des avantages de React Native est justement de pouvoir utiliser le même code pour toutes les plateformes. Du coup, il parait logique d'éviter cette multiplication de composant spécifiques.

Donc dans notre exemple, lors d'un changement d'option sur iOS, on appel directement la fonction du composant enfant pour recharger les favoris : this.refs['STARRED'].loadStar(); Aucune action n'est nécessaire du coté d'Android, car il passera dans ComponentDidMount pour charger les favoris à chaque fois.

On notera que l'on aurait aussi pu utiliser, dans nos composants, le code JS suivant pour gérer nos spécificités :

if (Platform.OS === 'android') {
   ...
} else {

}

De plus, nous aurions pu utiliser Redux, par exemple, pour nos problèmes de chargement de données.

Conclusion

React Native permet donc de créer des pages spécifiques pour chaque plateforme et d'utiliser des composants natifs pour chacun. Tout ceci se fait simplement et rapidement. Le seul détail qui peut prendre un peu de temps est la partie de création du style des menus, en particulier celui de Android. Mais on verra cette partie plus en détail lors d'un prochain article. Pour aller plus loin, n'hésitez pas à suivre notre formation à react Native !

Formations associées

Formations Mobile

Formation React Native

À distance (FOAD) Du 19 au 21 novembre 2024

Voir la formation

Formations Front end

Formation ReactJS

Toulouse Du 4 au 6 février 2025

Voir la formation

Actualités en lien

Image
Capture d'une partie de carte montrant un réseau de voies sur un fond de carte sombre. Au centre, une popup affiche les information de l'un des tronçons du réseau.
28/02/2024

Géné­rer un fichier PMTiles avec Tippe­ca­noe

Exemple de géné­ra­tion et d’af­fi­chage d’un jeu de tuiles vecto­rielles en PMTiles à partir de données publiques.

Voir l'article
Image
Read The Docs
01/02/2024

Publier une documentation VitePress sur Read The Docs

À l'origine, le site de documentation Read The Docs n'acceptait que les documentations Sphinx ou MKDocs. Depuis peu, le site laisse les mains libres pour builder sa documentation avec l'outil de son choix. Voici un exemple avec VitePress.

Voir l'article
Image
Widget
04/04/2023

Créer une application en tant que composant web avec Stencil

Mise en place dans le cadre de Geotrek, cette solution permet de se passer d'une iFrame pour afficher une application dans n'importe quel site.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus