contactez nous


React Native et Redux forment le duo vers lequel la plupart des équipes se tournent lorsqu'une application devient trop complexe pour se contenter de l'état local des composants. Ce guide vous montre comment les associer, comment conserver cet état après un redémarrage et comment déterminer si ce modèle est réellement pertinent pour votre projet. Voyez les choses ainsi : sans store, l'état est transmis de composant en composant dans l'arborescence, comme un colis que l'on se passe dans un couloir, chaque composant ne le détenant que pour le transmettre au suivant. Redux remplace ce couloir par une réserve. Une seule pièce, un seul registre, et n'importe quel écran peut consulter ce dont il a besoin sans déranger ses voisins.
Deux parcours s'offrent à vous sur cette page. Si vous êtes en plein développement, suivez le guide de haut en bas. Si vous êtes responsable technique ou fondateur et que vous vous demandez s'il faut adopter Redux, passez directement au test d'état en quatre questions et à la FAQ. Dans les deux cas, la question sous-jacente est autant commerciale que technique : une couche d'état prévisible demande un peu plus de code répétitif au départ, mais permet une intégration plus rapide et réduit les risques liés aux modifications ultérieures. Le test en quatre questions vous aidera à déterminer si cet investissement en vaut la peine.
Ce guide pour débutants porte sur Redux et Redux Toolkit dans une application React Native ; il suppose que vous maîtrisez déjà les bases de React Native. Vous débutez également sur ces sujets ? Commencez par notre guide sur React Native et Expo, ou consultez la documentation officielle de React Native, puis revenez ici.
Nous utilisons un émulateur Android tout au long de ce guide. Il simule un appareil Android sur votre ordinateur, vous permettant ainsi de tester votre application sur différents appareils et versions de l'API Android sans avoir à posséder chaque terminal physiquement. Il offre presque toutes les fonctionnalités d'un appareil réel. Notre guide React Native et Expo explique comment configurer cet environnement.
Pour illustrer nos propos, nous allons créer une application de compteur simple au fil de notre progression. Elle ressemblera à ceci :

Voici le code de notre composant SimpleCounter :
// components/SimpleCounter.js
import React from 'react';
import { View, Text, Button, TextInput } from 'react-native';
const SimpleCounter = () => (
<View>
<Text>0</Text>
<Button title="-" onPress={() => {}} />
<Button title="+" onPress={() => {}} />
<TextInput keyboardType="numeric" placeholder="Amount" />
<Button title="Change by amount" onPress={() => {}} />
</View>
);
export default SimpleCounter;Pour l'instant, ce code est statique. Aucun état n'a été déclaré dans le composant, et tous les exemples suivants s'appuient sur celui-ci. Une fois votre environnement prêt, installez redux et react-redux bibliothèques :
npm install redux react-reduxUne remarque sur la configuration : nous installons le package autonomereduxici afin que vous puissiez en comprendre les mécanismes fondamentaux. Pour un tout nouveau projet, le package que vous devriez utiliser est Redux Toolkit,npm install @reduxjs/toolkit react-redux, qui est la recommandation officielle de l'équipe Redux. Nous y viendrons plus tard dans ce guide, afin que vous compreniez ce qu'il fait pour vous.
Redux est une bibliothèque JavaScript destinée à la gestion de l'état de votre application. Elle vous offre un emplacement centralisé, appelé « store », où l'état est enregistré et modifié via des actions et des réducteurs. En d'autres termes, c'est à la fois l'entrepôt et le registre qui consigne qui a modifié quoi.
Cet emplacement unique vous permet de partager l'état entre les différents écrans et de savoir précisément où et comment il est modifié. Il devient indispensable pour les applications en pleine croissance, celles que personne ne peut appréhender dans leur globalité et qui deviennent instables précisément pour cette raison.
Redux gère l'état d'une application grâce à une combinaison d'actions, de réducteurs et d'un store. Découvrez comment ces trois abstractions s'articulent, le reste n'est que détail.

L'état d'une application représente toutes les informations qu'elle utilise ou modifie. Centralisez-le, définissez une méthode de modification prévisible, et vos écrans ne seront plus en contradiction sur les données réelles.
C'est crucial pour les applications monopages (SPA) complexes, c'est-à-dire les applications qui se chargent une seule fois et mettent à jour l'écran dynamiquement plutôt que de charger une nouvelle page à chaque interaction.
Les actions et les réducteurs modifient l'état de concert. Les actions déterminent ce qui est modifié et où. Les réducteurs précisent comment. En reprenant l'exemple du compteur au début de cet article, nous avons besoin de trois actions : INCREMENT, DECREMENT, et CHANGE_BY_AMOUNT.
Les actions sont des objets dotés d'un attribut type et d'un attribut payload . Le type est l'identifiant de l'action, et le payload contient toutes les informations nécessaires au réducteur pour modifier l'état. Nos deux premières actions ne font qu'incrémenter ou décrémenter le compteur de 1, elles n'ont donc besoin que d'un type. La troisième nécessite un payload pour indiquer la valeur du changement.
Déclarez vos actions dans un fichier séparé nommé Actions:
// redux/Actions.js
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
export const CHANGE_BY_AMOUNT = 'CHANGE_BY_AMOUNT';
export const increment = () => ({ type: INCREMENT });
export const decrement = () => ({ type: DECREMENT });
export const changeByAmount = (amount) => ({
type: CHANGE_BY_AMOUNT,
payload: { amount },
});Nommez vos actions en fonction de ce qui s'est produit, et non du gestionnaire que vous souhaitez exécuter. Dans nos projets, les noms d'actions qui ressemblent à des événements survivent aux refactorisations. Ceux qui ressemblent à des appels de fonction sont renommés dès que deux écrans nécessitent la même modification. Le guide de style Redux expose les mêmes arguments si vous souhaitez approfondir le raisonnement.
Passons à l'état initial. Il réside dans un fichier distinct, aux côtés du réducteur :
// redux/Reducer.js
import { INCREMENT, DECREMENT, CHANGE_BY_AMOUNT } from './Actions';
const initialState = {
counter: { amount: 0 },
};L'état initial contient un objet nommé counter avec un attribut amount , initialisé à 0. Vous remarquerez qu'il s'agit d'une constante plutôt que d'une variable, ce qui peut paraître étrange pour un élément décrit comme un état. Nous reviendrons sur la raison de ce choix.
Voici maintenant le réducteur, une fonction qui prend l'état actuel et l'action en arguments pour produire le nouvel état :
// redux/Reducer.js (continued)
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return { ...state, counter: { amount: state.counter.amount + 1 } };
case DECREMENT:
return { ...state, counter: { amount: state.counter.amount - 1 } };
case CHANGE_BY_AMOUNT:
return {
...state,
counter: { amount: state.counter.amount + action.payload.amount },
};
default:
return state;
}
};
export default counterReducer;Nous ne devons jamais muter l'état à l'intérieur d'un réducteur. Pourquoi ? Parce que le réducteur ne doit pas modifier directement l'objet d'état ; il doit renvoyer un nouvel objet qui deviendra le nouvel état. Le moteur de rendu de React compare l'objet d'état précédent avec le plus récent pour décider ce qui doit être redessiné.
Si vous modifiez l'état directement, React ne détecte aucun changement et conserve une vision erronée de l'état actuel de votre application. La documentation Redux sur les modèles de mise à jour immuables explique ces mécanismes en détail.
C'est pourquoi nous avons déclaré l'état initial comme une constante précédemment. C'est le seul objet de l'entrepôt sur lequel personne n'est autorisé à écrire.
Vient ensuite le store lui-même, l'objet où l'état est sauvegardé. La pratique courante consiste à le créer et à l'exporter depuis son propre fichier :
// redux/Store.js
import { createStore } from 'redux';
import counterReducer from './Reducer';
const store = createStore(counterReducer);
export default store;Attention :createStoreest officiellement obsolète depuis Redux 5.0.0, il apparaîtra donc barré dans votre éditeur. Il fonctionne toujours et continuera de fonctionner, ce qui est très bien pour apprendre les mécanismes ici, mais l'équipe Redux déconseille de l'utiliser, tout comme le package autonomeredux, directement dans du nouveau code. Son remplaçant moderne estconfigureStorede Redux Toolkit, que nous aborderons plus loin dans ce guide. Si vous voyez un avertissement d'obsolescence à cette étape, c'est normal.
Nous créons le store avec la méthode createStore() de Redux, en lui passant la fonction reducer définie précédemment. Une fois le store en place, nous pouvons invoquer des actions via la méthode dispatch, présentée plus loin dans ce guide, pour modifier l'état.
Maintenant, nous rendons le store disponible en le passant au composant Provider qui enveloppe SimpleCounter. Le Provider transmet le store à ce composant ainsi qu'à tout ce qu'il contient.
Provider provient de react-redux, la bibliothèque de liaison officielle pour React et React Native avec Redux. Voici à quoi cela ressemble :
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import store from './redux/Store';
import SimpleCounter from './components/SimpleCounter';
const App = () => (
<Provider store={store}>
<SimpleCounter />
</Provider>
);
export default App;Connectons maintenant nos composants au store. Dans les bases de code React Native actuelles, vous utilisez pour cela deux hooks de react-redux: useSelector lit une partie de l'état, et useDispatch renvoie la méthode dispatch afin que le composant puisse envoyer des actions en retour.
// components/SimpleCounter.js
import React, { useState } from 'react';
import { View, Text, Button, TextInput } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, changeByAmount } from '../redux/Actions';
const SimpleCounter = () => {
const amount = useSelector((state) => state.counter.amount);
const dispatch = useDispatch();
const [inputValue, setInputValue] = useState('0');
return (
<View>
<Text>{amount}</Text>
<Button title="-" onPress={() => dispatch(decrement())} />
<Button title="+" onPress={() => dispatch(increment())} />
<TextInput
keyboardType="numeric"
value={inputValue}
onChangeText={setInputValue}
/>
<Button
title="Change by amount"
onPress={() => dispatch(changeByAmount(Number(inputValue)))}
/>
</View>
);
};
export default SimpleCounter;Nous n'avons accès à l'objet d'état qu'à l'intérieur de useSelector car SimpleCounter est enveloppé dans le Provider. Le sélecteur reçoit l'état complet et ne renvoie que la valeur dont le composant a besoin ; ainsi, le composant est re-rendu lorsque state.counter.amount change, et reste inchangé lorsqu'une partie non liée du store est modifiée.
Pour cette raison, gardez vos sélecteurs aussi précis que possible. La plainte la plus fréquente concernant les performances de Redux dans React Native est celle d'une liste qui se re-rend à chaque frappe au clavier ; il s'agit presque toujours d'un sélecteur renvoyant une tranche entière, ou un objet nouvellement créé, alors qu'une seule valeur aurait suffi.
Les bases de code plus anciennes connectent les composants avec la méthode connect et une fonction mapStateToProps à la place. Elle fusionne l'objet renvoyé par mapStateToProps dans les props du composant, de sorte que la même valeur arrive sous la forme this.props.amount:
// legacy pattern, still valid in existing codebases
const mapStateToProps = (state) => ({ amount: state.counter.amount });
export default connect(mapStateToProps)(SimpleCounter);Les deux approches communiquent avec le même store. Les hooks sont le modèle recommandé pour le nouveau code et celui que nous utilisons pour le reste de ce guide. Apprenez connect tout de même, car vous le rencontrerez dans tout projet React Native écrit avant l'arrivée des hooks.
Nous disposons d'un store centralisé qui enregistre et modifie l'état de manière prévisible grâce aux actions et aux réducteurs. Vous avez peut-être remarqué une lacune : si vous fermez l'application et la rouvrez, le compteur revient à zéro.
C'est parce que rien ne persiste l'état. À chaque démarrage de l'application, le réducteur réinitialise le compteur à sa valeur initiale.
La persistance est essentielle dès lors que des informations doivent survivre à la session : jetons de connexion, paramètres de configuration ou brouillons en cours de rédaction. Dans React Native, vous pouvez l'obtenir avec la bibliothèque redux-persist .
Redux Persist écrit le store dans un stockage local persistant et le relit à chaque réouverture ou rafraîchissement de l'application. Nous utilisons ici un émulateur Android, mais cela fonctionne tout aussi bien sur iOS. Commencez par l'installer, ainsi qu' AsyncStorage, le magasin clé-valeur dans lequel il écrit :
npm install redux-persist @react-native-async-storage/async-storageModifiez ensuite le fichier Store.js comme suit :
// redux/Store.js
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
import counterReducer from './Reducer';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
};
const persistedReducer = persistReducer(persistConfig, counterReducer);
export const store = createStore(persistedReducer);
export const persistor = persistStore(store);Importez persistStore et persistReducer depuis redux-persist. Passez votre réducteur à persistReducer avec l'objet persistConfig , et vous obtenez un persistedReducer en retour.
Dans persistConfig , vous déclarez qu'AsyncStorage contiendra le store. AsyncStorage est le système de stockage clé-valeur de React Native ; il n'est pas chiffré, par conséquent, toute donnée sensible, et surtout les jetons d'authentification, doit être placée dans un stockage sécurisé.

Enfin, appelez persistStore pour assurer la persistance du store. Sur un projet plus important, vous ne souhaiterez peut-être pas que l'intégralité de l'état soit écrite sur le disque ; c'est précisément à cela que servent les options whitelist et blacklist dans persistConfig : choisissez les reducers qui méritent d'être persistés et laissez le reste. Le README de redux-persist documente ces deux options.
Pour finir, dans App.js, importez le persistor depuis Store.js et enveloppez SimpleCounter dans PersistGate. Il suspend l'affichage de l'interface jusqu'à ce que l'état enregistré soit récupéré et chargé dans le store, évitant ainsi aux utilisateurs de voir l'état initial s'afficher brièvement avant l'arrivée du contenu réel :
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './redux/Store';
import SimpleCounter from './components/SimpleCounter';
const App = () => (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<SimpleCounter />
</PersistGate>
</Provider>
);
export default App;Redux Toolkit est une bibliothèque conçue par les développeurs de Redux pour vous aider à créer une logique Redux plus efficace. C'est la solution recommandée par l'équipe Redux pour les nouveaux projets, et elle remplace la majeure partie du code précédent par une fraction de celui-ci.
C'est également devenu le standard de l'écosystème : Redux Toolkit est la recommandation officielle de l'équipe Redux pour tous les nouveaux projets, et la grande majorité des installations React-Redux l'intègrent désormais plutôt que de configurer Redux manuellement. Nous l'utilisons également en production. TrustPortal s'appuie sur Redux Toolkit pour maintenir un état prévisible au sein d'une application d'entreprise complexe, ce qui correspond exactement aux avantages décrits ici. Voici un tour d'horizon des fonctions les plus importantes.
createAction() pour déclarer des actionsRedux Toolkit nous offre une nouvelle façon de créer une action :
import { createAction } from '@reduxjs/toolkit';
export const increment = createAction('INCREMENT');
export const decrement = createAction('DECREMENT');
export const changeByAmount = createAction('CHANGE_BY_AMOUNT');createAction prend le type d'action comme argument et renvoie une fonction créatrice d'action. Appelez cette fonction, transmettez la charge utile (payload), et vous obtenez l'objet action. Vous pouvez également récupérer le type avec la méthode toString() , comme dans increment.toString(). Plus besoin de déclarer les types d'action sous forme de constantes, ce qui réduit considérablement le code répétitif.
createReducer() pour écrire des réducteurscreateReducer simplifie l'autre moitié du travail. Au lieu d'une instruction switch, vous associez chaque action à la fonction qui la gère, ce qui est beaucoup plus lisible, et les créateurs d'action renvoyés par createAction() peut être transmis directement à addCase(). En suivant la même logique de réducteur qu'auparavant :
import { createReducer } from '@reduxjs/toolkit';
import { increment, decrement, changeByAmount } from './Actions';
const initialState = { counter: { amount: 0 } };
const counterReducer = createReducer(initialState, (builder) => {
builder
.addCase(increment, (state) => ({
...state,
counter: { amount: state.counter.amount + 1 },
}))
.addCase(decrement, (state) => ({
...state,
counter: { amount: state.counter.amount - 1 },
}))
.addCase(changeByAmount, (state, action) => ({
...state,
counter: { amount: state.counter.amount + action.payload },
}));
});createReducer() utilise également Immer, une bibliothèque qui vous permet d'écrire du code qui semble modifier l'état tout en produisant discrètement une nouvelle copie en arrière-plan. Immer traduit chaque opération de mutation en une opération de copie équivalente. Ce qui signifie que nous pouvons écrire le réducteur comme ceci :
const counterReducer = createReducer(initialState, (builder) => {
builder
.addCase(increment, (state) => {
state.counter.amount += 1;
})
.addCase(decrement, (state) => {
state.counter.amount -= 1;
})
.addCase(changeByAmount, (state, action) => {
state.counter.amount += action.payload;
});
});Considérablement plus court. Même comportement.
createSlice() pour les actions et les réducteurs ensembleEn pratique, vous appelez rarement createAction et createReducer séparément. createSlice génère les deux à partir d'une seule définition : nommez la tranche (slice), donnez-lui un état initial et un ensemble de fonctions réductrices, et elle vous renvoie le réducteur ainsi qu'un créateur d'action correspondant pour chacun.
// redux/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { amount: 0 },
reducers: {
increment: (state) => {
state.amount += 1;
},
decrement: (state) => {
state.amount -= 1;
},
changeByAmount: (state, action) => {
state.amount += action.payload;
},
},
});
export const { increment, decrement, changeByAmount } = counterSlice.actions;
export default counterSlice.reducer;L'intégralité de Actions.js et Reducer.js paire précédente est regroupée dans ce seul fichier. Vos composants continuent d'utiliser useSelector et useDispatch exactement comme avant.
configureStore() pour créer le storeconfigureStore() enveloppe createStore() et configure des valeurs par défaut judicieuses, notamment la connexion aux Redux DevTools et le middleware par défaut, c'est-à-dire les fonctions par lesquelles chaque action passe avant d'atteindre le réducteur. Étant le successeur moderne de createStore, désormais obsolète, c'est la fonction que vous devriez privilégier pour tout nouveau projet.
Elle accepte également un objet de configuration plutôt qu'un ensemble de fonctions ; le réducteur est donc placé dans un objet, sous l'attribut reducer :
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
export const store = configureStore({
reducer: { counter: counterReducer },
});Utilisez redux-persist et Redux Toolkit dans le même projet et, tôt ou tard, vous rencontrerez l'erreur 'A non-serializable value was detected in an action'. La cause : configureStore() effectue une vérification de sérialisation, une protection lors du développement qui avertit lorsqu'une action contient un élément que Redux ne peut pas stocker en toute sécurité, comme une fonction ou une Promise, alors que redux-persist doit transmettre des fonctions dans ses propres actions.
La solution consiste à maintenir cette vérification active tout en en excluant les types d'actions de redux-persist :
import { configureStore } from '@reduxjs/toolkit';
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
import counterReducer from './counterSlice';
const persistConfig = { key: 'root', storage: AsyncStorage };
const persistedReducer = persistReducer(persistConfig, counterReducer);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
export const persistor = persistStore(store);Notez la différence entre exclure ces six types d'actions et désactiver complètement la vérification. Si vous la désactivez totalement, vous perdrez l'avertissement pour chaque valeur réellement non sérialisable que votre propre code pourrait insérer dans le store. La discussion et la solution se trouvent dans le ticket redux-persist sur la vérification de sérialisation.
createAsyncThunk et RTK QueryNotre compteur est synchrone. Presque aucune application réelle ne l'est. D'après notre expérience, la récupération de données est la raison la plus fréquente pour laquelle une équipe React Native adopte Redux : une requête possède un état de chargement, un état de succès et un état d'erreur, plusieurs écrans ont besoin de ces trois états, et les transmettre via des props devient rapidement ingérable.
Redux Toolkit propose deux solutions, et le choix entre les deux est la décision pratique à laquelle la plupart des équipes sont confrontées.
createAsyncThunk enveloppe une promesse et déclenche trois actions pour vous, une par phase, que vous gérez dans extraReducers:
// redux/counterSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
export const fetchCounter = createAsyncThunk(
'counter/fetch',
async (userId) => {
const response = await fetch(`https://api.example.com/counter/${userId}`);
return response.json();
},
);
const counterSlice = createSlice({
name: 'counter',
initialState: { amount: 0, status: 'idle', error: null },
reducers: {
increment: (state) => {
state.amount += 1;
},
},
extraReducers: (builder) => {
builder
.addCase(fetchCounter.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchCounter.fulfilled, (state, action) => {
state.status = 'succeeded';
state.amount = action.payload.amount;
})
.addCase(fetchCounter.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});Le composant déclenche le thunk et lit le statut :
const dispatch = useDispatch();
const { amount, status } = useSelector((state) => state.counter);
useEffect(() => {
if (status === 'idle') dispatch(fetchCounter(userId));
}, [status, dispatch, userId]);RTK Query va plus loin. Déclarez vos points de terminaison et il génère les thunks, les reducers, le cache et un hook par point de terminaison, de sorte que toute la gestion du chargement et des erreurs disparaît dans le hook :
// redux/api.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const api = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: 'https://api.example.com/' }),
endpoints: (builder) => ({
getCounter: builder.query({ query: (userId) => `counter/${userId}` }),
}),
});
export const { useGetCounterQuery } = api;
const { data, isLoading, error } = useGetCounterQuery(userId);Alors, lequel choisir ? Utilisez createAsyncThunk lorsque le travail asynchrone est un effet de bord que vous contrôlez, comme une séquence de connexion ou une synchronisation en arrière-plan. Utilisez RTK Query lorsque vous mettez en cache des données serveur, ce qui est le cas la plupart du temps sur mobile, car la mise en cache, le rechargement et l'invalidation sont précisément les aspects que les équipes gèrent mal manuellement. Mark Erikson, l'un des mainteneurs de Redux, explique pourquoi les thunks sont l'outil asynchrone par défaut dans cet article sur RTK et la logique asynchrone.
Notre guide sur comment gérer les opérations asynchrones avec Redux explore les thunks, les sagas et les alternatives via middleware. Pour un exemple concret en production du même problème de chargement, de mise en cache et de rechargement, Confinze a associé Redux à React Query dans un produit fintech, atteignant un taux de rétention de 85 % grâce à cette prévisibilité.
Redux n'est pas gratuit. Il ajoute des fichiers, de l'indirection et un modèle que chaque développeur de l'équipe doit apprendre. Avant de l'adopter sur un projet, nous effectuons le test des quatre questions sur l'état, et les réponses tranchent généralement la question :
useState est l'outil approprié.
Deux réponses « oui » ou plus, et Redux est justifié. Une seule ou aucune, et l'état natif de React combiné à Context vous seront plus utiles pour un coût moindre.
Nous avons emprunté les deux voies. Un outil interne avec un seul écran et un seul développeur est resté sur useState et a été livré plus rapidement grâce à cela. Une application de livraison avec des brouillons hors ligne, des mises à jour push et une équipe tournante a été réécrite avec Redux Toolkit, précisément parce que des bugs d'état survenaient simultanément de trois directions différentes. Sur AppTweak, une gestion rigoureuse de l'état dans un tableau de bord riche en données a permis de réduire le temps de chargement de 80 %, ce qui est le gain que ce test cherche réellement à évaluer.
Le cadre commercial reste pertinent dans les deux cas. Vous arbitrez entre un coût de configuration initial fixe et le coût des changements ultérieurs : la rapidité avec laquelle un nouveau développeur devient opérationnel, la confiance avec laquelle vous pouvez déployer une fonctionnalité touchant des données partagées, et la part de votre budget consacrée à la reproduction de bugs plutôt qu'au développement. Vous pouvez découvrir d'autres résultats dans nos études de cas.
Pas toujours. Depuis l'arrivée des hooks et de Context, de nombreuses applications gèrent leur état partagé sans lui. Redux reste pertinent lorsque l'état est lu et modifié depuis plusieurs écrans, doit persister après un redémarrage, ou est maintenu par une équipe plutôt que par un seul développeur. Pour un écran unique avec un état local, useState suffit.
Ils répondent à des besoins différents. Context transmet une valeur dans l'arborescence et déclenche un nouveau rendu pour chaque consommateur lors d'un changement, ce qui convient parfaitement à un thème ou une langue. Redux Toolkit apporte des mises à jour prévisibles, des rendus sélectifs via des sélecteurs, le voyage dans le temps avec les devtools et un emplacement documenté pour chaque modification d'état. Choisissez Context pour des valeurs peu fréquentes et de faible volume, et Redux Toolkit pour un état qui change souvent ou provient de sources multiples.
Installez redux-persist et AsyncStorage, enveloppez votre reducer avec persistReducer et une persistConfig, créez le persistor avec persistStore, puis enveloppez votre application dans PersistGate afin que l'interface attende le chargement de l'état stocké. Utilisez les options whitelist et blacklist pour ne persister que les tranches nécessaires, et conservez les jetons dans un stockage sécurisé plutôt que dans AsyncStorage, qui n'est pas chiffré.
Elle provient de configureStorede vérification de sérialisabilité avec les propres actions de redux-persist. Passez une option middleware à configureStore et ajoutez FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE et REGISTER à ignoredActions. Ne désactivez pas complètement la vérification, sous peine de perdre les avertissements concernant les valeurs réellement non sérialisables dans votre propre code.
createAsyncThunk ou RTK Query pour les appels API ?RTK Query pour les données serveur que vous souhaitez mettre en cache, actualiser et invalider, ce qui couvre la plupart des écrans mobiles. createAsyncThunk pour les effets secondaires que vous gérez de bout en bout, comme un processus de connexion ou une tâche de synchronisation. Les deux sont inclus dans Redux Toolkit, le choix se fait donc en fonction du cas d'utilisation plutôt que du projet.
Souvent, oui. Si l'application ne comporte qu'une poignée d'écrans, un seul développeur et aucune donnée persistante au-delà d'une session, le code répétitif (boilerplate) coûte plus cher qu'il ne rapporte. Faites le test des quatre questions sur l'état ci-dessus : avec moins de deux réponses positives, vous avez tout intérêt à utiliser useState et Context.
createStore, ou Redux Toolkit suffit-il ?Redux Toolkit suffit, et c'est ce que l'équipe Redux recommande pour les nouveaux projets. La fonction principale createStore est désormais obsolète. configureStore, createSlice et Immer remplacent les constantes d'action manuelles, les reducers avec switch et la configuration du store présentés plus tôt dans ce guide. Il vaut tout de même la peine de lire la forme longue une fois, car elle montre ce que le toolkit fait pour vous, et c'est ce que vous trouverez dans les bases de code plus anciennes.
Les actions décrivent ce qui s'est passé, les réducteurs déterminent comment l'état évolue, et le store conserve le résultat pour qu'il soit accessible depuis n'importe quel écran. Redux Toolkit élimine la majeure partie du code répétitif, RTK Query gère les données serveur, redux-persist maintient l'état après un redémarrage, et le test des quatre questions vous indique si l'adoption de ces outils est pertinente. Comme Redux est agnostique vis-à-vis de la vue, tout ce qui est présenté ici est également transférable à une application web React.
Vous évaluez la gestion d'état pour un produit mobile ou vous avez hérité d'une application dont l'état est devenu un goulot d'étranglement ? Notre équipe travaille sur ces problématiques au quotidien. Découvrez nos services de développement, ou parlez-nous de votre projet et nous vous dirons en toute franchise si Redux est la solution adaptée.


Étudiant en informatique et à temps partiel d'ImaginaryCloud. Désireux d'apprendre de nouvelles technologies et techniques. Joueur de tennis et pianiste.

Alexandra Mendes est Senior Growth Specialist chez Imaginary Cloud et possède plus de 3 ans d'expérience dans la rédaction sur le développement logiciel, l'IA et la transformation numérique. Après avoir suivi une formation en développement frontend, Alexandra a acquis des compétences pratiques en programmation et travaille désormais en étroite collaboration avec les équipes techniques. Passionnée par la manière dont les nouvelles technologies façonnent les entreprises et la société, Alexandra aime transformer des sujets complexes en contenus clairs et utiles pour les décideurs.
People who read this post, also found these interesting: