I have a functioning redux saga, but I can't stop thinking about how ugly it looks. What I'm trying to do is admittedly a little contrived to simulate async without needing it, but I want to delay one second and then call another function - similar to the tutorial. The difference from the tutorial (which is a simple incrementer) is that I actually need to pass along information. Here is how I'm doing it:
import { delay } from 'redux-saga';
import { put, call, takeEvery, all } from 'redux-saga/effects';
// Our worker Saga: will perform the add employee task
export function* addEmployeeAsync(action) {
yield call(delay, 1000);
console.log(action); // logs undefined on initial app load
const payload = action && action.payload;
yield put({ type: 'ADD_EMPLOYEE', payload });
}
// Our watcher Saga: spawn a new addEmployeeAsync task on each ADD_EMPLOYEE_ASYNC
export function* watchAddEmployeeAsync() {
yield takeEvery('ADD_EMPLOYEE_ASYNC', addEmployeeAsync);
}
export default function* rootSaga() {
yield all([
addEmployeeAsync(),
watchAddEmployeeAsync(),
]);
}
The function is also being called on page load with a payload of undefined
, which may indicate a larger problem I am missing.
The complete code base is here: https://github.com/LukeSchlangen/react-salary-calculator/tree/9ce96409080a3a3f702465791cd28c4c83cadc6f
To reiterate, this code is working, but I can't help but think that there must be a cleaner way to do this.
Create a plain JavaScript Object to instruct the middleware that we need to dispatch some action, and let the middleware perform the real dispatch. This way we can test the Generator's dispatch in the same way: by inspecting the yielded Effect and making sure it contains the correct instructions.
takeEvery - enables the use of several fetchData objects at the same time. At a given moment, we can start a new fetchData task while there are still one or more previous fetchData tasks which have not yet terminated. takeLatest - Only one fetchData task can be active at any given moment.
Calling a saga from another saga is as simply as doing a call effect.
Such a powerful & elegant tool as Redux-Saga, a Redux side effect manager, is said to be deprecated, and no longer being maintained, starting from Jan 27, 2021.
I think I found it. I don't think I need to export the worker saga in the all
at the bottom of the file. I think just exporting the watcher saga takes care of it (and prevents the initial call where the payload is undefined).
Here is what I ended up with:
import { delay } from 'redux-saga';
import { put, call, takeEvery, all } from 'redux-saga/effects';
// Our worker Saga: will perform the add employee task
export function* addEmployeeAsync({ payload }) {
yield call(delay, 1000);
yield put({ type: 'ADD_EMPLOYEE', payload });
}
// Our watcher Saga: spawn a new addEmployeeAsync task on each ADD_EMPLOYEE_ASYNC
export function* watchAddEmployeeAsync() {
yield takeEvery('ADD_EMPLOYEE_ASYNC', addEmployeeAsync);
}
export default function* rootSaga() {
yield all([
watchAddEmployeeAsync(),
]);
}
This seems much cleaner to me (since I don't have to do the check to see if it is undefined).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With