2017-10-12 8 views
0

J'essaie de comprendre comment incorporer l'annulation de plusieurs tâches du même type d'action dans redux-saga. Fondamentalement, quand mon composant est dans componentWillUnmount(), je veux annuler toutes les tâches qu'il a peut-être commencé.redux-saga: Annulation de plusieurs tâches du même type d'action/saga

Si je l'action suivante (ce qui est grandement simplifiée de ce que j'ai fait dans mon code, mais je suis en train de réduire ce à l'essentiel):

// Action 
export const loadMyData = params => { 
    let url = /* Create URL based on params */ 
    return { 
    type: FETCH_DATA, 
    url, 
    key: /* a unique key so we can retrieve it in the state later */ 
    } 
} 

Et la saga suivante: Comme indiqué ci-dessus, le composant peut appeler plusieurs fois loadMyData(). En outre, il peut y avoir d'autres composants qui appellent également loadMyData(). J'essaie donc de trouver un moyen d'annuler les tâches à partir du seul composant qui est dans l'état componentWillUnmount(), mais de laisser toutes les autres tâches en cours d'exécution intactes.

Dans le Redux Saga Cancellation documentation, leur exemple est pour une seule tâche qui attend une action d'annulation après. Et je ne peux pas comprendre comment l'étendre à mon cas d'utilisation.

Répondre

1

Ce qui me vient à l'esprit est la suivante:

En componentWillMount vous enregistrez votre composant en envoyant une action et le stockage des tâches dans un réducteur comme ceci:

registerWatchFetchData = (componentKey) => { 
    return { 
    type: "REGISTER_WATCH_FETCH_DATA", 
    payload: { componentKey } 
    } 
} 

réducteur:

// ... 
case "REGISTER_WATCH_FETCH_DATA": 
    return {...state, tasks: {...state.tasks, [action.payload.componentKey]: []}} 

Ensuite, à l'intérieur de function* watchFetchData(), vous stockez la nouvelle tâche dans le réducteur pour la saisie de composant correspondante sur componentKey que vous fournissez i n le payload:

export function* watchFetchData() { 
    while (true) { 
    let action = yield take(FETCH_DATA); 
    let task = yield fork(fetchApi, action); 
    yield put({ type: "STORE_TASK", payload: { componentKey: action.payload.componentKey, task } }) 
    } 
} 

puis ajouter au réducteur

// ... 
case "STORE_TASK": 
    return {...state, tasks: {...state.tasks, [action.payload.componentKey]: [...state.tasks[action.payload.componentKey], action.payload.task]}} 

Et componentWillUnmount vous décomposez une autre action pour raconter une saga de tirer toutes les tâches pour le componentKey, itérer et de les annuler tout comme ainsi:

function* watchUnregisterComponent(){ 
    while(true){ 
     const action = yield take("UNREGISTER_WATCH_FETCH_DATA") 
     const componentTasks = yield select(state => state.myReducer.tasks[action.payload.componentKey]) 
     componentTasks.forEach((t) => { 
      yield cancel(t) 
     }) 
     // dispatch another action to delete them from the reducer 
    } 
}