We are using https://github.com/react-boilerplate/react-boilerplate and have a classic store layout with multiple components.
We have a redux store for adding products to the cart, which has a side effect saga to save the added product to the cart database.
Because there are multiple positions to add products to cart, we have used the same CartContainer on one page 3 times (the Cart itself, the product listing and in another product listing).
The problem we have now, is that the api will be called 3 times.
I guess that is because, by using the container 3 times, we also injected the Saga three times.
My question is now: What is the correct approach to only inject the Saga once, without having to rewrite all of the sagas again and again?
This is my saga:
import {
call,
put,
select,
takeLatest,
} from 'redux-saga/effects';
import {getRequest, putRequest} from '../../utils/request';
import {ADD_PRODUCT, LOAD_PRODUCTS} from './constants';
import {
addProductSuccess,
addProductError,
productsLoaded,
productsLoadingError,
} from './actions';
import {makeSelectProduct, makeSelectUserId} from './selectors';
/**
* Github repos request/response handler
*/
export function* getProducts() {
const requestURL = '/api/orders';
const user_id = yield select(makeSelectUserId());
try {
let itemsData = yield call(getRequest, requestURL, user_id);
if (itemsData) {
itemsData = itemsData.slice(-1).items;
}
yield put(productsLoaded(itemsData));
} catch (err) {
yield put(productsLoadingError(err));
}
}
/**
* Github repos request/response handler
*/
export function* addProduct() {
const requestURL = '/api/cart';
const productData = yield select(makeSelectProduct());
try {
const orderData = yield call(putRequest, requestURL, productData);
yield put(addProductSuccess(orderData.id));
} catch (err) {
yield put(addProductError(err));
}
}
/**
* Root saga manages watcher lifecycle
*/
export default function* root() {
yield [
takeLatest(ADD_PRODUCT, addProduct),
takeLatest(LOAD_PRODUCTS, getProducts),
];
}
And this is the export part of my container:
export function mapDispatchToProps(dispatch) {
return {
onAddProduct: (id, quantity, variant) => {
dispatch(addProduct(id, quantity, variant));
},
onLoadProducts: (user_id) => {
dispatch(loadProducts(user_id));
},
};
}
const mapStateToProps = createStructuredSelector({
products: makeSelectProducts(),
});
const withConnect = connect(mapStateToProps, mapDispatchToProps);
const withReducer = injectReducer({key: 'cart', reducer});
const withSaga = injectSaga({key: 'cart', saga});
export default compose(withReducer, withConnect)(CartContainer);
sagaMiddleware.run(defaultSaga);
which can be exposed fromexport const sagaMiddleware = createSagaMiddleware();
from wherever you are including saga middleware. Does this work for u? – Brominate