-->

How to pass args from sagaMiddleware to action wat

2019-07-10 08:52发布

问题:

I'm new to Sagas, Use to come from a redux-thunk background, So I'm not sure what is the best way to pass arguments to my final action. I will appreciate some kind of "For dummy answer"

The thing is, I have some object called session in my store.js I create this session in the sagaMiddleware, but in order to make my functions in the sagas work, I always need to interact with this object.

So, the question is. Using my current code, how is possible to pass some args (In this case "session" to the final action in sagas.js)

store.js here it is "session"

sagaMiddleware.run(function* () {
    yield* saga1(session);
    yield* saga2(session);
  });

saga1.js

Expor actions:

export default function* root() {
  yield [
    fork(watchAction1),
    fork(watchAction2),
  ];
}

Actions watcher

function* watchMyAction() {
  yield takeEvery(actionTypes.SEND_EVENT, myAction);
}

Action

function* myAction(action) { // Here I want again the sesssion
  // Action.payload stuff, here I want my session arg from loadStore.js
}

回答1:

There are multiple ways to do what you want and picking one depends on both your use case and preference.

The pass it down method

The simplest way is just to pass down the object all the way down to myAction saga.

yield* saga1(session)
...
fork(watchAction1, session)
...
yield takeEvery(actionTypes.SEND_EVENT, myAction, session)
...
function* myAction(session, action) {
    console.log(session);
}

This is good enough solution if you have only few sagas or if the structure of your sagas is flat so you don't have to pass it down too deep.

The import method

Another way to go about this is to import the session object. If you need to do some initialization first, you can create a file that exports a singleton object, like so:

// session.js
import Session from 'session-library';

const config = {foo: 'bar'};
export default new Session(config);

Now you can import this file wherever you need to access your session. You don't need to pass it through multiple files/sagas just to get it to one of your sagas deep down. However, it can be a bit more problematic if you need to replace the session object.

// action.js
import session from 'path/to/session';

function* myAction(action) {
    console.log(session);
}

The context method

The third method is to use the setContext/getContext effects. This one is my personal favorite as it doesn't rely on the module system, doesn't require any special files and you can request access to the objects like session at the exact moment you need it - even midway saga execution.

// store.js
const stuffYouWantToAccess = {session};
sagaMiddleware.run(function* (stuffYouWantToAccess) {
    yield setContext(stuffYouWantToAccess);
   ...
}, stuffYouWantToAccess);

// action.js

function* myAction(action) {
    const session = yield getContext('session');
    console.log(session);
}

It also isn't perfect though as context works a bit like global variables and you need to access the context values using string names ('session') which can be sometimes a problem (e.g. when using closure compiler or typechecking).

So pick your poison :)