redux-saga / redux-saga

An alternative side effect model for Redux apps

Home Page:https://redux-saga.js.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Waiting for an action with takeMaybe / take after END is dispatched for SSR

sandeepahuja-stack opened this issue · comments

Waiting for an action with takeMaybe / take after END is dispatched for SSR

function actionStateUpdate(data){
  return {
   type : 'STATE_UPDATE',
   payload: data
  }
}
function *abc(action){
  const response = yield call(api);
  yield put(actionStateUpdate, response);
  // state is getting updated 
  const state = yield select();
}

function *xyz(action){
  // used both take/takeMaybe
  const wantsToUseActionPayload = yield takeMaybe('STATE_UPDATE');
  console.log("here", wantsToUseActionPayload)
  //in case of take, console is not getting printed
  // in case of takeMayBe  getting => { type: '@@redux-saga/CHANNEL_END' }

  const state = yield select();
  // unable to found updated state 
}

Using Next Js and next redux wrapper
in Get server side props,

store.dispatch(END as any) 
await store.sagaTask.toPromise()

faicing similar issue

facing similar issue

@klis87 , can you help on this? as facing the same issue

Greetings! Could you please provide a repo with everything setup so we can better investigate the issue?

Hi @neurosnap
Thanks for quick response
unable to provide the repo

But here are my findings
In server side, We have to dispatch the END

store.dispatch(END as any) 
await store.sagaTask.toPromise()

The middleware provides a special action END. If you dispatch the END
action, then all Sagas blocked on a take Effect will be terminated regardless
of the specified pattern. If the terminated Saga has still some forked tasks
which are still running, it will wait for all the child tasks to terminate
before terminating the Task.

as per my observation, here we can't use take then we are using takeMaybe (https://redux-saga.js.org/docs/api/#takemaybepattern)

const wantsToUseActionPayload = yield takeMaybe('STATE_UPDATE');
console.log(wantsToUseActionPayload) // { type: '@@redux-saga/CHANNEL_END' }

Requirement: We need to consume the response in xyz*, which comes from the api in abc*

Hi @neurosnap, @Andarist

Could anyone please let us know the ways to handle multiple inter dependent saga on SSR?

My understanding is: (please correct me if misunderstading)
when calling yield put(actionStateUpdate, response); in the generator abc. the action has been called. If you debug into the reducer, the code such as state.data = action.payload should have been executed. But at this time the store/state may not be applied the latest data even if you complete yield takeMaybe('STATE_UPDATE'); or yield take() call.
I don't know why. It may be related to the event loop of the redux-saga. the put call in the saga is a micro task, the state may not be updated until a macro task is called.
So, you can try to add yield delay(100); or call or setTimeout, etc. before yield select(); to init a macro task to ensure the state is updated (queued micro-tasks will be executed)