Redux Saga: modelli che usiamo
In questo post, ci immergeremo in Redux Saga, che è un framework JavaScript utilizzato per gestire gli effetti collaterali nella nostra applicazione web. In un post precedente, ci ho presentato i concetti principali di Redux Saga . Se hai appena iniziato con Redux Saga, ti consiglio di iniziare da lì.
Gli argomenti specifici che tratteremo sono:
- Esecuzione di una saga una volta con
take, invece ditakeLatestotakeEvery - Aspettando la prima azione finita con
race - Condivisione di servizi attraverso la tua app con
getContext
Esecuzione di una saga una volta con take, invece di takeLatestotakeEvery
All'interno delle nostre saghe di slice, di solito usiamo takeLatesto takeEvery, di cui ho parlato nel mio post precedente . Per la maggior parte dei casi d'uso, vogliamo considerare ogni azione rilevata.
Ma cosa succede se siamo interessati solo alla prima occorrenza di un'azione come la prima volta che l'utente interagisce con un modulo? Come sarebbe questa implementazione nella nostra saga di slice? L'API Redux Saga non offre un metodo specifico per questo, ma come stiamo per vedere, c'è un modo semplice per farlo.
Innanzitutto, un codice boilerplate:
function* changePasswordSubmittedHandler() {
// ...
}
function* changePasswordSaga() {
yield all([
takeLatest(CHANGE_PASSWORD_SUBMITTED, changePasswordSubmittedHandler)
])
}
Ora aggiungiamo un gestore che vogliamo venga attivato solo una volta.
function* changePasswordSubmittedHandler() {
// ...
}
function* changePasswordFormFocusedHandler() {
yield take(CHANGE_PASSWORD_FORM_FOCUSED)
// ...
}
function* changePasswordSaga() {
yield all([
takeLatest(CHANGE_PASSWORD_SUBMITTED, changePasswordSubmittedHandler),
changePasswordFormFocusedHandler()
])
}
Cosa sta succedendo qui? L'esecuzione changePasswordFormFocusedHandlerda sola, anziché con takeLatesto takeEveryci consente di eseguire il gestore una sola volta. L' takeistruzione all'inizio mette in pausa la funzione . Solo una volta che la nostra app rileva il CHANGE_PASSWORD_FORM_FOCUSEDproblema, si riattiva ed esegue il resto della funzione.
Un approccio alternativo consisterebbe nell'includere un flag nello stato globale della tua app che puoi capovolgere una volta che si è verificata la prima occorrenza. Ma se vuoi evitare di aggiungere proprietà allo stato, questo approccio funziona bene.
Aspettando la prima azione finita conrace
A volte vogliamo ascoltare diverse azioni e intraprendere passaggi specifici a seconda di quale di queste azioni è stata completata per prima. Ad esempio, quando un utente invia il pagamento per un ordine, la transazione può essere completata correttamente o potrebbe fallire per una serie di motivi. Per questo scenario, ci rivolgiamo al racecombinatore di effetti. Redux Saga si riferisce a racee allcome combinatori di effetti perché entrambi accettano 1 o più effetti e li gestiscono contemporaneamente.
Vediamo come racefunziona:
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
}
}
Questo è un approccio utile alla gestione delle richieste asincrone. Usiamo race per i seguenti scenari:
- caricamento e inizializzazione di SDK e librerie
- recupero di segmenti di informazioni utente
- gestire i reindirizzamenti
- convalida della ricerca
- gestione dei gettoni
- Eventi UI come quello qui sotto:
const { closed } = yield race({
confirmed: take(AGE_VERIFICATION_MODAL_CONFIRMED),
closed: take(AGE_VERIFICATION_MODAL_CLOSED)
})
Se vogliamo avere accesso a determinati servizi (o contesti) che possono essere condivisi durante le nostre saghe, possiamo utilizzare getContext. Con una configurazione rapida, possiamo facilmente accedere a metodi che possono chiamare API, LocalStorage, meccanismi di registrazione e middleware.
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)
Fatto ciò, possiamo accedere a questi contesti nelle nostre saghe di slice con 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 })
}
}
Conclusione
Questi modelli ingegnosi fungono da approcci affidabili per la gestione di un ambiente dinamico come lo stato globale di un'enorme applicazione web. Forse in un post futuro, documenterò alcuni altri schemi che usiamo a Just Eat Takeaway. Fammi sapere se ti piacerebbe leggerlo!

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































