Jeeva J
Jeeva J

Reputation: 3253

Redux Saga - all the watches called for a dispatch action

I have declared the following saga api.

export function* watchSaveProducts() {
  yield takeLatest(ProductActionTypes.PRODUCT_SAVE_REQUEST, saveProducts);
}

export const saga = function* productSagasContainer() {
  yield all([watchGetProducts(), watchSaveProducts()]);
};

When I dispatch an action from the container, both the saga watches triggered. But in that I am just calling only getProducts. Even If I do save products, then getProducts triggered before save products.

    componentDidMount() {
    this.props.getProducts();
  }

The dispatch props like follow

const mapDispatchToProps = (dispatch: any) => ({
  getProducts: () => dispatch(productActions.getProducts()),
  saveProduct: (ids: number[]) => dispatch(productActions.saveProduct(ids)),
});

Upvotes: 1

Views: 1258

Answers (1)

frangaliana
frangaliana

Reputation: 803

You're throwing both methods when you do this:

export const saga = function* productSagasContainer() {
  yield all([watchGetProducts(), watchSaveProducts()]);
};

Therefore, both will always be running.

I'll explain my structure when I work with redux and sagas:

  1. First, create a sagaMiddleware to connect redux-store with sagas (extracted from the redux-saga documentation) :
import createSagaMiddleware from 'redux-saga'
import reducer from './path/to/reducer'

export default function configureStore(initialState) {
  // Note: passing middleware as the last argument to createStore requires redux@>=3.1.0
  const sagaMiddleware = createSagaMiddleware()
  return {
    ...createStore(reducer, initialState, applyMiddleware(/* other middleware, */sagaMiddleware)),
    runSaga: sagaMiddleware.run(rootSaga)
  }
}
  1. Define rootSaga with sagas divided into application parts:
export function* rootSaga() {
  yield all([fork(sample1Watcher), fork(sample2Watcher)]);
}
  1. Create the set of sagas that will be launched in this part depending on the action that is dispatched
export function* sample1Watcher() {
  yield takeLatest(ProductActionTypes.GET_PRODUCT_REQUEST, getProduct);
  yield takeLatest(ProductActionTypes.PRODUCT_SAVE_REQUEST, saveProduct);
}
  1. Define each of the methods, for example the get:
function* getProduct() {
  try {
    yield put({ type: actionTypes.SET_PRODUCTS_LOADING });

    const data = yield call(products.fetchProductsAsync);

    yield put({ type: actionTypes.GET_PRODUCTS_COMPLETE, payload: data });

  } catch (e) {
    console.log("Error");
  }
}
  1. Finally, define action method in dispatchToProps and launch it wherever you want:
const mapDispatchToProps = (dispatch: any) => ({
  getProducts: () => dispatch(productActions.getProducts()),
  saveProduct: (ids: number[]) => dispatch(productActions.saveProduct(ids)),
});
componentDidMount() {
  this.props.getProducts();
}

Upvotes: 1

Related Questions