what would be the difference between the two approaches below?
export function* watchLoginUser() {
yield takeEvery(USER_LOGIN, loginUser)
}
export function* watchLogoutUser() {
yield takeEvery(USER_LOGOUT, logoutUser)
}
export function* watchGetParties() {
yield takeEvery(PARTIES_GET, getParties)
}
export default function* root() {
yield [
fork(watchLoginUser),
fork(watchLogoutUser),
fork(watchGetParties)
]
}
export default function* root() {
yield [
takeEvery(USER_LOGIN, loginUser),
takeEvery(USER_LOGOUT, logoutUser),
takeEvery(PARTIES_GET, getParties)
]
}
When do I need to use fork and when not?
In general,
fork
is useful when a saga needs to start a non-blocking task. Non-blocking here means: the caller starts the task and continues executing without waiting for it to complete.There is a variety of situations where this can be useful, but the 2 main ones are:
Your top-level saga can be an example of the first use-case. You'll likely have something like:
Where
authSaga
will likely include things like:You can see that this example is equivalent to what you suggested, calling with
fork
a saga yielding atakeEvery
call. But in practice, you only need to do this for code organisation purposes.takeEvery
is itself a forked task, so in most cases, this would be uselessly redundant.An example of the second use-case would be something like:
You can see in this example that the
monitorUserProfileUpdates
will execute while the caller saga resumes, and gets to wait to theUSER_SIGNED_OUT
action to be dispatched. It can in addition keep a reference to it in order to cancel it when needed.For the sake of completeness, there is another way to start non-blocking calls:
spawn
.fork
andspawn
differ in how errors and cancellations bubble from child to parent saga.