Redux Saga : modèles que nous utilisons
Dans cet article, nous plongerons dans Redux Saga, qui est un framework JavaScript utilisé pour gérer les effets secondaires dans notre application Web. Dans un post précédent, je nous ai présenté les principaux concepts de Redux Saga . Si vous débutez avec Redux Saga, je vous recommande de commencer par là.
Les sujets spécifiques que nous aborderons sont :
- Lancer une saga une fois avec
take, au lieu detakeLatestoutakeEvery - En attendant la première action terminée avec
race - Partager des services sur votre application avec
getContext
Lancer une saga une fois avec take, au lieu de takeLatestoutakeEvery
À l'intérieur de nos sagas de tranches, nous utilisons généralement takeLatestor takeEvery, dont j'ai parlé dans mon précédent post . Dans la plupart des cas d'utilisation, nous souhaitons prendre en compte chaque action détectée.
Mais que se passe-t-il si nous ne nous intéressons qu'à la première occurrence d'une action, comme la première fois que l'utilisateur interagit avec un formulaire ? À quoi ressemblerait cette implémentation dans notre saga slice ? L'API Redux Saga n'offre pas de méthode spécifique pour cela, mais comme nous allons le voir, il existe un moyen simple de s'y prendre.
Tout d'abord, un code passe-partout :
function* changePasswordSubmittedHandler() {
// ...
}
function* changePasswordSaga() {
yield all([
takeLatest(CHANGE_PASSWORD_SUBMITTED, changePasswordSubmittedHandler)
])
}
Ajoutons maintenant un gestionnaire que nous ne voulons déclencher qu'une seule fois.
function* changePasswordSubmittedHandler() {
// ...
}
function* changePasswordFormFocusedHandler() {
yield take(CHANGE_PASSWORD_FORM_FOCUSED)
// ...
}
function* changePasswordSaga() {
yield all([
takeLatest(CHANGE_PASSWORD_SUBMITTED, changePasswordSubmittedHandler),
changePasswordFormFocusedHandler()
])
}
Qu'est-ce qu'il se passe ici? L'exécution changePasswordFormFocusedHandlerpar lui-même, plutôt qu'avec takeLatestou takeEverynous permet d'exécuter le gestionnaire une fois et une seule. L' takeinstruction au début provoque la pause de la fonction . Ce n'est qu'une fois que notre application détecte qu'elle CHANGE_PASSWORD_FORM_FOCUSEDreprendra sa pause et exécutera le reste de la fonction.
Une approche alternative consisterait à inclure un indicateur dans l'état global de votre application que vous pouvez inverser une fois que la première occurrence s'est produite. Mais si vous voulez éviter d'ajouter des propriétés à l'état, cette approche fonctionne bien.
En attendant la première action terminée avecrace
Parfois, nous voulons écouter plusieurs actions et prendre des mesures spécifiques en fonction de laquelle de ces actions s'est terminée en premier. Par exemple, lorsqu'un utilisateur soumet le paiement d'une commande, la transaction peut se terminer avec succès ou échouer pour un certain nombre de raisons. Pour ce scénario, nous nous tournons vers le racecombinateur d'effets. Redux Saga fait référence à raceet allen tant que combinateurs d'effets car ils acceptent tous les deux 1 ou plusieurs effets et les gèrent simultanément.
Voyons comment racefonctionne :
function* paymentSubmittedHandler() {
const { failed, finished, cancelled } = yield race({
failed: take(PAYMENT_SUBMISSION_FAILED),
finished: take(PAYMENT_SUBMISSION_FINISHED),
cancelled: take(PAYMENT_SUBMISSION_CANCELLED)
})
if (finished) {
// do something
}
if (cancelled || failed) {
// do something
}
}
Il s'agit d'une approche utile pour gérer les requêtes asynchrones. Nous utilisons race pour les scénarios suivants :
- chargement et initialisation des SDK et des bibliothèques
- récupérer des segments d'informations sur l'utilisateur
- gestion des redirections
- validation de la recherche
- gestion des jetons
- Événements d'interface utilisateur comme celui ci-dessous :
const { closed } = yield race({
confirmed: take(AGE_VERIFICATION_MODAL_CONFIRMED),
closed: take(AGE_VERIFICATION_MODAL_CLOSED)
})
Si nous voulons avoir accès à certains services (ou contextes) qui peuvent être partagés tout au long de nos sagas, nous pouvons utiliser getContext. Avec une configuration rapide, nous pouvons facilement accéder à des méthodes qui peuvent appeler des API, LocalStorage, des mécanismes de journalisation et des intergiciels.
import createSagaMiddleware from 'redux-saga'
const cookieStorage = {
save: value => {
// save the cookie
}
}
const logger = {
logInfo: info => {
// log the info
}
}
const sagaMiddleware = createSagaMiddleware({
context: {
cookieStorage,
logger
}
})
sagaMiddleware.run(rootSaga)
Une fois cela fait, nous pouvons accéder à ces contextes dans nos sagas de tranches avec getContext.
function* cookiePreferenceStorageSaga() {
try {
const { cookieStorage } = yield getContext('cookieStorage')
const key = 'foobar'
yield call(cookieStorage.save, key)
yield put(cookiePreferenceStorageSucceeded())
} catch (error) {
const logger = yield getContext('logger')
logger.logInfo('Cookie preference storage error', { error })
}
}
Conclusion
Ces modèles astucieux servent d'approches fiables pour gérer un environnement dynamique comme l'état global d'une application Web massive. Peut-être que dans un prochain article, je documenterai d'autres modèles que nous utilisons chez Just Eat Takeaway. Faites-moi savoir si vous souhaitez lire à ce sujet!
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































