Infinite loop with redux-saga
I know you found your answer, that's great. I had the same symptoms but a different problem and a different solution.
I am not using normal constants for my actions, I am using the constants from my actions so that I only need to write it in a single location. It's a setup I have. However I realised an issue today. My code looks like the following
export const deleteArendeAction = {
will: arende => ({
type: "WILL_TA_BORT_ARENDEN",
...arende,
}),
did: payload => ({
type: "DID_TA_BORT_ARENDEN",
...payload,
}),
error: payload => ({
type: "DID_DELETE_ARENDE_ERROR",
...payload,
}),
}
function* deleteArenden(arende) {
try {
yield arendeApi.deleteArende(arende.id)
} catch (error) {
yield put(deleteArendeAction.error(arende))
return
}
yield put(deleteArendeAction.did(arende))
}
export function* deleteArendeSaga() {
yield takeEvery(deleteArendeAction.will().type, deleteArenden)
}
My code looks something like that.
It kept triggering my takeEvery infinitely.
It turns out, yield put(deleteArendeAction.did(arende))
this part was the culprit. Because the variable arende
had the value of { type: "WILL_TA_BORT_ARENDEN", ... }
which caused some sort of bug, triggering the event again.
Technically, that shouldn't happen I think? But it did.
So if you come across this question and the answer doesn't solve your problem. Then double-check what you send into your put
:P
Of course, you explicitly set the infinite loop the next lines:
yield put({type: 'SHOW_DETAIL', response: response.data})
// ...
yield takeEvery('SHOW_DETAIL', fetchDetailsAsync)
The saga doesn't do any magic things for you, and only is a preliminary layer of a subscription and generation on actions and executions coroutines.
SOLUTION:
You shall use different names for actions which you catch from React components, and actions which are used for optimistical and real up-dating of a status.
Use yield takeEvery('SHOW_DETAIL_REQUEST', fetchDetailsAsync)
and name your action in this manner.
Use yield put({type: 'SHOW_DETAIL_SUCCESS', response: response.data})
in success response and name your reducer in this manner
More than that, you can use 'SHOW_DETAIL_FAILURE'
for failed saga request.
All names above are common-used case.