Redux-saga: Dynamicall forking and cancelling all sagas in a file

Created on 21 Mar 2017  路  1Comment  路  Source: redux-saga/redux-saga

I'm trying to create a root saga function which takes all saga functions in the file, forks them and then cancels them on a certain action (LOCATION_CHANGE in this case).

This is what I have so far:

// Example saga function, if it's relevant
function getImageVersionsRequest(id) {
  return http(getRequest(`/images/${id}/versions`, 'GET'))
    .then((response) => (Promise.resolve(response)))
    .catch((error) => {
      throw (error);
    });
}

function* getImageVersions(action) {
  const { id } = action.payload;
  try {
    const response = yield call(getImageVersionsRequest, id);
    const versionsDropdownState = {
      options: response.data,
      selected: response.data[0],
    };
    yield put({ type: SET_VERSIONS_DROPDOWN_STATE, payload: { versionsDropdownState } });
  } catch (error) {
    console.log(error); // eslint-disable-line no-console
  }
}

export function* getImageVersionsFlow() {
  yield* takeLatest(GET_IMAGE_VERSIONS, getImageVersions); // eslint-disable-line redux-saga/yield-effects
}


// relevant code
export function* root() {
  // get all exported functions
  const fileExports = require('./sagas.js'); // eslint-disable-line global-require

  // remove root and default exports
  delete fileExports.default;
  delete fileExports.root;

  // convert to array
  const functions = _.values(fileExports);

  // fork sagas and add to sagas
  const sagas = [];
  functions.forEach((saga) => sagas.push(fork(saga)));
  yield sagas;


  // when location changes, cancel all sagas
  yield take(LOCATION_CHANGE);
  yield cancel(...sagas);
}

export default [root];

However, I'm getting the following error:
_Error: cancel(task): argument [object Object] is not a valid Task object_

From what I can tell, I follow the API guidelines listed on this github... can anyone spot the error and point me in the right direction?

I gathered some ideas from the following post: https://github.com/redux-saga/redux-saga/issues/178

question

Most helpful comment

From what I see this should be sufficient:

function getImageVersionsRequest(id) {
  return http(getRequest(`/images/${id}/versions`, 'GET'));
}

As to this part:

  // fork sagas and add to sagas
  const sagas = [];
  functions.forEach((saga) => sagas.push(fork(saga)));
  yield sagas;

Instead of iterating by forEach I would suggest just mapping over it, so it would become

const sagas = functions.map(saga => fork(saga))

also if you want to get your task descriptors which u could cancel u need to assign them to the variable, so

const tasks = yield sagas;

and later on you can cancel them like this

yield tasks.map(task => cancel(task))

>All comments

From what I see this should be sufficient:

function getImageVersionsRequest(id) {
  return http(getRequest(`/images/${id}/versions`, 'GET'));
}

As to this part:

  // fork sagas and add to sagas
  const sagas = [];
  functions.forEach((saga) => sagas.push(fork(saga)));
  yield sagas;

Instead of iterating by forEach I would suggest just mapping over it, so it would become

const sagas = functions.map(saga => fork(saga))

also if you want to get your task descriptors which u could cancel u need to assign them to the variable, so

const tasks = yield sagas;

and later on you can cancel them like this

yield tasks.map(task => cancel(task))
Was this page helpful?
0 / 5 - 0 ratings

Related issues

NullVoxPopuli picture NullVoxPopuli  路  3Comments

oliversisson picture oliversisson  路  3Comments

stevenmusumeche picture stevenmusumeche  路  3Comments

sompylasar picture sompylasar  路  3Comments

tobyl picture tobyl  路  3Comments