Correct way to pass redux saga payload to another action
Asked Answered
R

1

6

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.

Rothenberg answered 4/2, 2018 at 16:28 Comment(0)
R
13

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).

Rothenberg answered 4/2, 2018 at 19:10 Comment(1)
Yup, that's the way to go. The way I usually do it on the projects is that I have a file App.saga.js where I gather all sagas and have something like your rootSaga and then on every module I have a saga file that holds something similar to what you have with the takeEvery and everything else. Good job!Characharabanc

© 2022 - 2024 — McMap. All rights reserved.