You might start out with a saga that looks something like the following code.
No problem, it runs perfectly.
function* fetchSomethingSaga() { // Run this saga forever while (true) { // Wait for a fetch request const action = yield take(Action.FETCH_SOMETHING_REQUEST); // Extract the id of what we need to fetch const id = action.payload; try { // Make the API call const thing = yield call(apiClient.get, `/thing/${id}`); // We succeeded, return the thing yield put(fetchSomethingSuccess(thing)); } catch (err) { // We failed, report the error yield put(fetchSomethingFailure(err)); } }}
At some point, you decide to replace take with takeEvery so your saga can handle concurrent requests. Or you replace it with takeLatest so you can process the most recent request.
But... your events start firing in an infinite loop. Hey, what gives?
Problem Code
function* fetchSomethingSaga() { while (true) { yield takeEvery(Action.FETCH_SOMETHING_REQUEST, fetchSomething); }}function* fetchSomething(action) { const id = action.payload; try { const something = yield call(apiClient.get, `/something/${id}`); yield put(fetchSomethingSuccess(something)); catch (err) { yield put(fetchSomethingFailure(err)); }}
The problem is that takeEvery/takeLatest were put in a loop, which is unnecessary because they already have a loop internally.
The Solution
Fix your outer saga by removing the loop.
function* fetchSomethingSaga() { yield takeEvery(Action.FETCH_SOMETHING_REQUEST, fetchSomething);}
And have a quick refresher on takeEvery from the redux-saga documentation.
Happy coding!