【问题标题】:redux-saga: Cancelling multiple tasks of the same action type / sagaredux-saga:取消相同动作类型/saga的多个任务
【发布时间】:2017-10-12 23:53:06
【问题描述】:

我试图弄清楚如何在 redux-saga 中合并取消多个相同动作类型的任务。基本上,当我的组件在componentWillUnmount() 中时,我想取消它可能已经启动的所有任务。

如果我有以下操作(这与我在代码中的实际操作相比已大大简化,但我正在尝试将其缩减为基本要素):

// 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 */
  }
}

还有以下传奇:

// Saga
export function* fetchData(action) {
  try {
    // 'callApi()' currently uses axios
    let response = yield call(callApi, action.url);

    yield put({
      type: FETCH_SUCCESS,
      key: action.key,
      payload: response.data
   });
  } catch(error) {
    yield put({
      type: FETCH_FAILURE,
      error
    });
  }
}

export function* watchFetchData() {
  while (true) {
    let action = yield take(FETCH_DATA);
    let task = yield fork(fetchApi, action);
  }
}

如上所述,组件可能会多次调用loadMyData()。此外,可能还有其他组件也调用loadMyData()。因此,我试图找到一种方法来取消仅处于 componentWillUnmount() 状态的组件中的任务,但保留任何其他正在运行的任务。

Redux Saga Cancellation documentation 中,他们的示例是针对需要取消操作的单个任务。而且我不知道如何将其扩展到我的用例。

【问题讨论】:

    标签: reactjs redux redux-saga


    【解决方案1】:

    我想到的是:

    componentWillMount 中,您通过分派一个操作并将任务存储在一个reducer 中来注册您的组件,如下所示:

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

    减速器:

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

    然后在function* watchFetchData() 中,您将新任务存储在reducer 中,以获取您在payload 中提供的componentKey 上的相应组件键控:

    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 } })
      }
    }
    

    然后添加到reducer

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

    componentWillUnmount 中,您调度另一个动作来告诉 saga 为 componentKey 拉取所有任务,遍历它们并取消它们,如下所示:

    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
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-11
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多