简体   繁体   中英

Redux-saga takeLatest conditionally

I have a question related to redux-saga that is there any way to achieve takeLatest but with condition.

For example, I have a dynamical list of song types (Rap, Pop, Hip_hop...), I want to fetch the songs by song type. I define an redux-action with type "FETCH_SONGS_BY_TYPE" then pass songType to it. The action will look like

// actions
const fetchSongsByType = songType => ({
  type: FETCH_SONGS_BY_TYPE,
  songType
});
--------------------------------------------------
//saga
function* fetchSongsByTypeSaga(action) {
   // request songs list by action.songType
}
function* Saga() {
  yield takeLatest(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}

So I want that the previous saga task is only canceled if the next saga run has the same songType.

In above code, I got this:

  1. fetchSongs - songType: Hip_hop (canceled because of [2])
  2. fetchSongs - songType: Rap (canceled because of [3])
  3. fetchSongs - songType: Pop (canceled because of [4])
  4. fetchSongs - songType: Rap (canceled because of [5])
  5. fetchSongs - songType: Pop

But I expected it will be like this:

  1. fetchSongs - songType: Hip_hop
  2. fetchSongs - songType: Rap (canceled because of [4])
  3. fetchSongs - songType: Pop (canceled because of [5])
  4. fetchSongs - songType: Rap
  5. fetchSongs - songType: Pop

I appreciate any helps, thanks in advance.

If you take a look at the documentation oftakeLatest , you will see how this effect is built using the low-level effects. With this example, you can easily create your custom effect which only cancels actions from the same music genre.

takeLatestByType:

const takeLatestByType = (patternOrChannel, saga, ...args) => fork(function*() {
  // hold a reference to each forked saga identified by the type property
  let lastTasks = {};

  while (true) {
    const action = yield take(patternOrChannel);

    // if there is a forked saga running with the same type, cancel it.
    if (lastTasks[action.type]) {
      yield cancel(lastTasks[action.type]);
    }

    lastTasks[action.type] = yield fork(saga, ...args.concat(action));
  }
});

Usage:

function* Saga() {
  yield takeLatestByType(FETCH_SONGS_BY_TYPE, fetchSongsByTypeSaga);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM