Is there a way to wait for an action in redux-sagas?
Asked Answered
D

4

17

I have a saga (A) which fetches the API. This is tied with action (a). I want to trigger an action (b) which internally calls (a), waits for it to finish and then yield something.

// saga A -> action_a
function *saga_a(action) {
  yield put( ...action1...);
  yield call(api, ...params);
  yield put( ...action2...);
}


// saga B -> action_b
function *saga_b(action) {
  yield put(..action3..)

  waitFor -- put(action_a)     <------ how to achieve this?

  yield put(..action4..)
 }
Dwyer answered 27/6, 2017 at 21:12 Comment(2)
Does await put(action_a) work?Graziano
Is there a way without await?Dwyer
D
23

Yes, there is. You can use take to achieve this.

function *saga_b(action) {
  ...

  yield take('action_a') // this will put the saga_b essentially on hold until `action_a` is handled by the reducer

  ...
}

UPDATE

You can use saga-toolkit in order to put and wait for actions without take-ing them:

const resultOfFetchSomething = yield putAsync(fetchSomething()) // dispatches action "fetchSomething" & wait for the saga that is attached to it to finish running
Dentelle answered 28/3, 2018 at 23:30 Comment(2)
to be clear, its held off until action_a is handled by reducerCottingham
take(patternOrChannel): argument [object Object] is not valid channel or a valid pattern... In which world where you able to take an action? also put(action); take('actionType'); doesn't workInsoluble
P
4

The way I do it my code bases is by calling the other saga directly. It unfortunately couples the two together, but since you need to wait the coupling will at least be more explicit.

function *saga_b(action) {
  yield put(..action3..)
  yield call(saga_a, action_a)
  yield put(..action4..)
}
Pishogue answered 1/7, 2017 at 14:57 Comment(1)
This is what I ended up doing. I was hoping for a cleaner way of doing it. But I guess there is none. Thanks for the answer.Dwyer
R
1

Use call instead put and call directly SAGA generator instead action, like:

yield call(saga_a, {payload: {param1: "param_one", param2: "param_two"}, type: 'unique_name')
Ricoriki answered 21/7, 2023 at 8:30 Comment(0)
B
0

This is a bit late but I struggled with the same thing and believe people still have the same problem. I had to write my own extensions to achieve this functionality. see https://github.com/kutlugsahin/redux-saga-callback

Eventually you will be able to do this

// saga B -> action_b
function *saga_b(action) {
  yield put(..action3..)

  yield putWait(action_a)     <------ how to achieve this?

  yield put(..action4..)
 }
Bozovich answered 20/10, 2019 at 16:51 Comment(1)
There's a package that also solves this issue (with putAsync) among others: npmjs.com/package/saga-toolkitDentelle

© 2022 - 2024 — McMap. All rights reserved.