Reputation: 830
I'm working on a project that involves multiple saga and reducers. Some of the saga used, are similar, I want to re-use their logic across various components.
Current implementation:
function* fetchUpComingMovies() {
try {
const res = yield call(getUpComingMovies);
const { status, data } = res;
if (status === 200 && data) {
yield put(successGetUpComingMovies(res.data.results));
}
} catch (error) {
yield put(failureGetUpComingMovies(error?.message));
}
}
function* fetchCurrentShows() {
try {
const res = yield call(getOnTheAirShows);
const { status, data } = res;
if (status === 200 && data) {
yield put(successGetCurrentShows(res.data.results));
}
} catch (error) {
yield put(failureGetCurrentShows(error?.message));
}
}
function* fetchTopRated({ payload }) {
try {
const res = yield call(getTopRated, payload);
const { status, data } = res;
if (status === 200 && data) {
yield put(successGetTopRated(res.data.results));
}
} catch (error) {
yield put(failureGetTopRated(error?.message));
}
}
export default function* rootSaga() {
yield all([
takeLatest(homeActionTypes.REQUEST_GET_UPCOMING_MOVIES, fetchUpComingMovies),
takeLatest(homeActionTypes.REQUEST_GET_SHOWS, fetchCurrentShows),
takeLatest(homeActionTypes.REQUEST_GET_TOP_RATED, fetchTopRated),
]);}
As you can see, the code inside the try/catch block is similar, just the corresponding actions are different. There are more such sagas in other components. I feel like I'm repeating the code and want to re-use the functionality across components. How to solve this issue?
Any help would be appreciated. Thanks
Upvotes: 0
Views: 303
Reputation: 102367
You can use a saga factory to produce the sagas.
import { call, put, all, takeLatest } from 'redux-saga/effects';
// api
const getUpComingMovies = () => [];
const getOnTheAirShows = () => [];
// action creator
const successGetUpComingMovies = (payload) => ({ type: 'SUCCESS_GET_UP_COMING_MOVIES', payload });
const failureGetUpComingMovies = (payload) => ({ type: 'FAILURE_GET_UP_COMING_MOVIES', payload });
const successGetCurrentShows = (payload) => ({ type: 'SUCCESS_GET_CURRENT_SHOWS', payload });
const failureGetCurrentShows = (payload) => ({ type: 'FAILURE_GET_CURRENT_SHOWS', payload });
function sagaFactory(opts) {
return function* saga(...args) {
try {
const res = yield call(opts.api, ...args);
const { status, data } = res;
if (status === 200 && data) {
yield put(opts.successActionCreator(res.data.results));
}
} catch (error) {
yield put(opts.failureActionCreator(error?.message));
}
};
}
export default function* rootSaga() {
yield all([
takeLatest(
'REQUEST_GET_UPCOMING_MOVIES',
sagaFactory({
api: getUpComingMovies,
successActionCreator: successGetUpComingMovies,
failureActionCreator: failureGetUpComingMovies,
}),
),
takeLatest(
'REQUEST_GET_SHOWS',
sagaFactory({
api: getOnTheAirShows,
successActionCreator: successGetCurrentShows,
failureActionCreator: failureGetCurrentShows,
}),
),
]);
}
Upvotes: 1