Recherche de site Web

Introduction à l'utilisation de Redux dans une application React Native


Introduction

Redux est un conteneur d'état prévisible pour les applications JavaScript. Si Redux est nouveau pour vous, nous vous recommandons de consulter notre introduction à Redux.

Dans cet article, vous apprendrez comment persister les données utilisateur en utilisant Redux dans une application React Native. L'application est un réseau social fictif avec un HomeScreen affichant le nombre d'amis connectés, et un FriendsScreen affichant une liste d'amis potentiels à ajouter. Vous utiliserez Redux pour partager l'état entre les deux écrans.

Prérequis

Pour compléter ce tutoriel, vous aurez besoin de :

  • Un environnement de développement local pour Node.js. Suivez Comment installer Node.js et créer un environnement de développement local.
  • Il peut être utile de se familiariser avec la configuration de votre environnement pour créer un nouveau projet React Native et utiliser les simulateurs iOS ou Android.

Ce tutoriel s'appuie sur les sujets abordés dans Comment utiliser le routage avec React Navigation dans React Native. Il est recommandé de lire ce tutoriel pour mieux comprendre le fonctionnement du projet, mais ce n'est pas obligatoire.

Ce tutoriel a été vérifié avec Node v14.7.0, npm v6.14.7, react v16.13.1, react-native v0.63.2, @react-navigation/native v5.7.3, @react-navigation/stack v5.9.0, redux v4.0.5, et react-redux v7.2.1.

Étape 1 — Configuration du projet et installation de Redux

Ce tutoriel utilisera une version modifiée du code dans Comment utiliser le routage avec React Navigation dans React Native. Pour commencer, clonez MySocialNetwork :

git clone https://github.com/do-community/MySocialNetwork.git

Ensuite, accédez au répertoire du projet :

cd MySocialNetwork

Changez la branche git en redux-starter :

git checkout redux-starter

Ensuite, installez les dépendances du projet :

npm install

Ensuite, installez les bibliothèques redux et react-redux dans le projet :

npm install redux@4.0.5 react-redux@7.2.1

Votre projet est maintenant configuré et vos dépendances ont été installées.

Étape 2 — Création d'un réducteur

Pour connecter Redux à votre application, vous devrez créer un réducteur et une action.

Tout d'abord, vous allez créer un réducteur d'amis. Un réducteur est une fonction pure qui prend l'état précédent et une action comme arguments et retourne un nouvel état. Le réducteur est essentiel pour maintenir à jour l'état actuel des amis dans toute l'application au fur et à mesure des changements.

Créez le fichier FriendsReducer.js à la racine du projet :

nano FriendsReducer.js

Ajoutez le code suivant :

import { combineReducers } from 'redux';

const INITIAL_STATE = {
  current: [],
  possible: [
    'Alice',
    'Bob',
    'Sammy',
  ],
};

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    default:
      return state
  }
};

export default combineReducers({
  friends: friendsReducer
});

Dans ce fichier, vous créez une variable INITIAL_STATE avec des amis possibles à ajouter à votre réseau social. Ensuite, vous exportez friendsReducer en tant que propriété appelée friends.

Avec votre réducteur en place, vous aurez besoin d'un moyen d'ajouter des amis.

Étape 3 — Créer une action

Les actions sont des objets JavaScript qui représentent des charges utiles d'informations et qui envoient des données de votre application au Redux store.

Les actions ont un type et un payload optionnel. Dans ce tutoriel, le type sera ADD_FRIEND, et le payload sera l'indice du tableau d'un ami que vous ajoutez dans le tableau current des amis.

Créez le fichier FriendsActions.js à la racine du projet :

nano FriendsActions.js

Ajoutez addFriend :

export const addFriend = friendsIndex => (
  {
    type: 'ADD_FRIEND',
    payload: friendsIndex,
  }
);

Lorsqu'un utilisateur clique sur un ami, ce code récupérera le friendsIndex du tableau friends.possible. Vous devrez maintenant utiliser cet index pour déplacer cet ami dans le tableau friends.current.

Revisitez FriendsReducer.js :

nano FriendsReducer.js

Ajoutez ADD_FRIEND :

// ...

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case 'ADD_FRIEND':
      // Pulls current and possible out of previous state
      // We do not want to alter state directly in case
      // another action is altering it at the same time
      const {
        current,
        possible,
      } = state;

      // Pull friend out of friends.possible
      // Note that action.payload === friendIndex
      const addedFriend = possible.splice(action.payload, 1);

      // And put friend in friends.current
      current.push(addedFriend);

      // Finally, update the redux state
      const newState = { current, possible };
  
      return newState;

    default:
      return state
  }
};

// ...

Ce code extrait les amis actuels et possibles de l'état précédent. Array.splice() récupère l'ami du tableau des amis possibles. Array.push ajoute l'ami au tableau des amis actuels. Après que les modifications sont effectuées, l'état est mis à jour.

Maintenant, vous avez un réducteur et une action. Vous devrez appliquer le réducteur à votre application.

Étape 4 — Ajouter le réducteur à l'application

Vous devrez fournir l'état friends de votre application en utilisant le composant Provider de React Redux.

Ouvrez App.js :

nano App.js

Importez Provider, createStore et friendsReducer :

import 'react-native-gesture-handler';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import friendsReducer from './FriendsReducer';
import HomeScreen from './HomeScreen';
import FriendsScreen from './FriendsScreen';

// ...

Ajoutez et remplacez le code surligné par createStore et Provider :

// ...

const store = createStore(friendsReducer);

class App extends React.Component {
  // ...

  render() {
    return (
      <Provider store={store}>
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Screen
              name="Home"
              component={HomeScreen}
            />
            <Stack.Screen
              name="Friends"
              component={FriendsScreen}
            />
          </Stack.Navigator>
        </NavigationContainer>
      </Provider>
    )
  }
}

Maintenant, friends sont accessibles dans votre application, mais vous devez encore les ajouter à HomeScreen et FriendsScreen.

Étape 5 — Ajouter Redux aux écrans

À cette étape, vous rendrez friends accessible à vos écrans avec la fonction mapStateToProps. Cette fonction mappe le state du FriendsReducer vers les props dans les deux écrans.

Commençons par HomeScreen.js. Ouvrez le fichier HomeScreen.js :

nano HomeScreen.js

Ajoutez et remplacez les lignes de code surlignées dans HomeScreen.js :

import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>You have (undefined) friends.</Text>

        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = (state) => {
  const { friends } = state
  return { friends }
};

export default connect(mapStateToProps)(HomeScreen);

Ce changement de code ajoute react-redux et rend friends disponible pour le HomeScreen.

Ensuite, ajoutez des valeurs pour les amis actuels (this.props.friends.current) :

class HomeScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>You have { this.props.friends.current.length } friends.</Text>

        <Button
          title="Add some friends"
          onPress={() =>
            this.props.navigation.navigate('Friends')
          }
        />
      </View>
    );
  }
}

Votre HomeScreen affichera désormais le nombre d'amis actuels. Vous pouvez maintenant passer à la FriendsScreen.

Ouvrez FriendsScreen.js :

nano FriendsScreen.js

Ajoutez et remplacez les lignes de code surlignées dans FriendsScreen.js :

import React from 'react';
import { connect } from 'react-redux';
import { StyleSheet, Text, View, Button } from 'react-native';

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = (state) => {
  const { friends } = state
  return { friends }
};

export default connect(mapStateToProps)(FriendsScreen);

Ce changement de code ajoute react-redux et rend friends disponible pour le FriendsScreen.

Ajoutez des valeurs pour les amis possibles (props.friends.possible) :

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        {
          this.props.friends.possible.map((friend, index) => (
            <Button
              key={ friend }
              title={ `Add ${ friend }` }
            />
          ))
        }

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

Maintenant, lorsque vous naviguez vers le FriendsScreen, vous verrez tous les amis possibles provenant du reducer.

Enfin, ajoutez la nouvelle action Redux addFriend à FriendsScreen.js :

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { StyleSheet, Text, View, Button } from 'react-native';
import { addFriend } from './FriendsActions';

class FriendsScreen extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Add friends here!</Text>

        {
          this.props.friends.possible.map((friend, index) => (
            <Button
              key={ friend }
              title={ `Add ${ friend }` }
              onPress={() =>
                this.props.addFriend(index)
              }
            />
          ))
        }

        <Button
          title="Back to home"
          onPress={() =>
            this.props.navigation.navigate('Home')
          }
        />
      </View>
    );
  }
}

// ...

const mapDispatchToProps = dispatch => (
  bindActionCreators({
    addFriend,
  }, dispatch)
);

export default connect(mapStateToProps, mapDispatchToProps)(FriendsScreen);

Ajoutons deux amis au réseau social et revenons à HomeScreen pour voir combien d'amis l'utilisateur a actuellement :

Avec cela, vous avez déplacé toute la logique de App.js vers Redux, ce qui rend votre application beaucoup plus flexible, surtout à mesure que vous ajoutez plus de pages et de fonctionnalités comme l'authentification et l'intégration de bases de données.

Avant de conclure, nettoyons le code.

Étape 6 — Nettoyage

Maintenant que vous utilisez Redux, vous n'aurez plus besoin des props que vous passiez depuis App.js.

Vous pouvez pousser le nettoyage plus loin en stockant vos types action dans un fichier séparé.

Vous utilisez la chaîne 'ADD_FRIEND' à deux endroits : dans l'action et dans le reducer des amis. C'est dangereux, car si vous changez la chaîne à un endroit et pas à l'autre, vous pourriez casser votre application. À mesure que votre application grandit, il est logique de garder tous ces types d'action dans un fichier appelé types.js.

Créez le fichier types.js au niveau racine :

nano types.js

Ajoutez le code suivant :

export const ADD_FRIEND = 'ADD_FRIEND';

Ensuite, revisitez FriendsActions.js pour utiliser le nouveau ADD_FRIEND :

nano FriendsActions.js

Remplacez le 'ADD_FRIEND' entre guillemets par la variable ADD_FRIEND dans votre action :

import { ADD_FRIEND } from './types';

export const addFriend = friendsIndex => (
  {
    type: ADD_FRIEND,
    payload: friendsIndex,
  }
);

Ensuite, revenez à FriendsReducer.js pour utiliser également le nouveau ADD_FRIEND :

nano FriendsReducer.js

Changez le 'ADD_FRIEND' entre guillemets en la variable ADD_FRIEND dans votre reducer :

import { combineReducers } from 'redux';
import { ADD_FRIEND } from './types';

// ...

const friendsReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case ADD_FRIEND:
      // ...

    default:
      return state;
  }
};

Cela rend l'application moins fragile. Lors du développement de vos applications, vous devriez être conscient des opportunités de consolider le code et d'éviter de vous répéter.

Conclusion

Dans ce tutoriel, vous avez couvert redux, reducers, actions et la gestion de données évolutive.

Il y a beaucoup plus de choses que vous pouvez faire avec Redux, depuis la synchronisation des données avec une base de données, jusqu'à l'authentification et le suivi des autorisations des utilisateurs.

Le code source complet de ce tutoriel est disponible sur GitHub.

Si vous souhaitez en savoir plus sur React, jetez un œil à notre série Comment coder en React.js, ou consultez notre page sur le sujet React pour des exercices et des projets de programmation.