Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

please explain: uncaught at check runSaga, saga argument must be a Generator function

I am following a tutorial on pluralsight, which is a full-stack react/redux tutorial, and I am creating a saga.mock.js file with the following code.

this is something im unfamiliar with and would appreciate and explanation so i can understand this.

import { take, put, select } from 'redux-saga/effects';
import * as mutations from './mutations';
import uuid from 'uuid';

export default function* taskCreationSaga(){
    while (true) {
            const {groupID} = yield take(mutations.REQUEST_TASK_CREATION);
            console.log("Got group ID", groupID);
    }
}

then in my store's index.js I added the bottom code in the asterisks**

import { createStore, applyMiddleware } from 'redux';
import { defaultState } from '../../server/defaultState';
import { createLogger } from 'redux-logger';
import createSagaMiddleware from 'redux-saga';

const sagaMiddleware = createSagaMiddleware();
import * as sagas from './sagas.mock'

export const store = createStore(
    function reducer(state = defaultState, action) {
        return state;
    },
    **applyMiddleware(createLogger(), sagaMiddleware)
);

for (let saga in sagas) {
    sagaMiddleware.run();
}**

and recieved the following error, "uncaught at check runSaga(storeInterface, saga, ...args): saga argument must be a Generator function!"

I solved this problem by changing this:

for (let saga in sagas) {
    sagaMiddleware.run();
}

to this:

for (let saga in sagas) {
    sagaMiddleware.run(sagas[saga]);
}
like image 761
humans Avatar asked Mar 30 '19 04:03

humans


2 Answers

The documentation is asking you to give the run() method a generator function, so you can just pass the default generator taskCreationSaga and import it from sagas.mock.js file

import { taskCreationSaga } from './sagas.mock';

for (let saga in sagas) {
   sagaMiddleware.run(taskCreationSaga)
}

This should work with you and allow you to continue the course.

like image 83
rvisas Avatar answered Sep 22 '22 13:09

rvisas


The run() method should receive an array of sagas (which each saga is a generator function) that each returns a generator object. That way the middleware can treat asynchronous procedures to follow an ordered sequence of operations via calling the next on each saga which may also start other sagas.

I was looking for an explanation for this as well, and found it in the redux-saga docs: (here is the part that explains the use of run() in more details)

In the first iteration, the middleware invokes the next() method to retrieve the next Effect. The middleware then executes the yielded Effect as specified by the Effects API below. Meanwhile, the Generator will be suspended until the effect execution terminates. Upon receiving the result of the execution, the middleware calls next(result) on the Generator passing it the retrieved result as an argument. This process is repeated until the Generator terminates normally or by throwing some error.

If the execution results in an error (as specified by each Effect creator) then the throw(error) method of the Generator is called instead. If the Generator function defines a try/catch surrounding the current yield instruction, then the catch block will be invoked by the underlying Generator runtime. The runtime will also invoke any corresponding finally block.

In the case, a Saga is canceled (either manually or using the provided Effects), the middleware will invoke return() method of the Generator. This will cause the Generator to skip directly to the finally block.

like image 39
Tomer Avatar answered Sep 22 '22 13:09

Tomer