If we look at GraphRequestManager.start
.
const that = this;
const callback = (error, result, response) => {
if (response) {
that.requestCallbacks.forEach((innerCallback, index, array) => {
if (innerCallback) {
// here it is called as a normal callback, not a generator
innerCallback(response[index][0], response[index][1]);
}
});
}
if (that.batchCallback) {
that.batchCallback(error, result);
}
};
NativeGraphRequestManager.start(this.requestBatch, timeout || 0, callback); } ```
The callback you pass is invoked as a normal Function
, as opposed to a GeneratorFunction
.
And since they differ in how they are executed, that's why nothing happens, since your GeneratorFunction
, when invoked, is just instantiated and sits there until getting garbage collected.
So the preferred option to solve this, which is aligned with the redux-saga
flow is using eventChannel
, which keeps the flow inside redux-saga
and is actually advised for similar cases.
The other one, not so preferable, would be to just call raw store.dispatch
, it obviously breaks through the abstraction levels and flow of redux-saga
, but still gets the job done, by invoking some other saga
action which can handle call
ing your startFacebookRegister
with the response
.
EventChannel
We need to wrap the whole GraphRequestManager...
block into an eventChannel
, so we can redirect the response
or error
back into saga flow from the vendor control.
Can be something like this:
import {
cancelled,
call,
take,
put
} from "redux-saga/effects";
import {
eventChannel,
END
} from 'redux-saga';
function* startFacebookRegister(err, res) {
const {
id,
email,
first_name,
last_name
} = res;
yield put(initFacebookLogin.success(res));
}
function* graphRequestWrapper() {
return eventChannel(emit => {
const infoRequest = new GraphRequest(
'/me', {
httpMethod: 'GET',
version: 'v2.5',
parameters: {
'fields': {
'string': 'email,first_name,last_name,id'
}
}
}, (err, res) => {
if (err) {
emit(new Error(err));
} else {
emit(res);
}
emit(END);
});
// BTW infoRequest variable should be instantiated before we
// can add it with addRequest, just a side note
new GraphRequestManager().addRequest(infoRequest).start();
return () => {
// clean up
};
})
}
export function* mainSaga() {
const chan = yield call(graphRequestWrapper);
while (true) {
try {
const res = yield take(chan);
yield call(startFacebookRegister, null, res);
} catch (err) {
yield call(startFacebookRegister, err);
} finally() {
if (yield cancelled()) chan.close()
}
}
}
Store Dispatch
And with store, you can export your store
from your main.js
or index.js
where you createStore
it with all the reducers and middlewares, and use it here directly.
import store "../exported/from/somewhere";
function* startFacebookRegister({payload}) {
const {
id,
email,
first_name,
last_name
} = payload;
yield put(initFacebookLogin.success(res));
}
function graphRequestWrapper() {
const infoRequest = new GraphRequest(
'/me', {
httpMethod: 'GET',
version: 'v2.5',
parameters: {
'fields': {
'string': 'email,first_name,last_name,id'
}
}
}, (err, response) => {
store.dispatch({type: "INIT_FACEBOOK_LOGIN_REQUEST_SUCCESS_SAGA", payload: {...response}})
});
new GraphRequestManager().addRequest(infoRequest).start();
}
function* mainSaga() {
yield takeLatest("INIT_FACEBOOK_LOGIN_REQUEST_SUCCESS_SAGA", startFacebookRegister);
yield call(graphRequestWrapper);
}