links: React MOC
Problem
Some times user might click a button multiple times as there might be delay in UI updation like showing Loading Indicator, which will result in duplicate API calls to the Backend
function* submit({data}) {
try {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: true});
const response = yield call(Api.submit, payload)
if(response) {
yield put({type: ActionTypes.SUBMIT_SUCCESS, payload: response});
}
} catch (e) {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: false});
yield put({type: ActionTypes.SUBMIT_ERROR, payload: true});
}
}
// Some Feature Saga that contains multiple sagas
function* meetingSaga() {
yield takeLatest(ActionTypes.HANDLE_SUBMIT, submit)
}The takeLatest automatically cancels any existing sagas and forks new saga, so if we add a small delay to the submit method it will wait for that delay before it makes an API call, which is the desired behaviour as we don’t want to trigger duplicate API calls to BE
The above code becomes like this
function* submit({data}) {
try {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: true});
yield call(delay, 500)
const response = yield call(Api.submit, payload)
if(response) {
yield put({type: ActionTypes.SUBMIT_SUCCESS, payload: response});
}
} catch (e) {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: false});
yield put({type: ActionTypes.SUBMIT_ERROR, payload: true});
}
}
// Some Feature Saga that contains multiple sagas
function* meetingSaga() {
yield takeLatest(ActionTypes.HANDLE_SUBMIT, submit)
}The takeLatest basically does this
function* watchInput() {
let task
while (true) {
const { input } = yield take('INPUT_CHANGED')
if (task) {
yield cancel(task)
}
task = yield fork(handleInput, input)
}
}There is another utility method called debounce from redux-saga which can be used like this
function* submit({data}) {
try {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: true});
yield call(delay, 500)
const response = yield call(Api.submit, payload)
if(response) {
yield put({type: ActionTypes.SUBMIT_SUCCESS, payload: response});
}
} catch (e) {
yield put({type: ActionTypes.SUBMIT_LOADING, payload: false});
yield put({type: ActionTypes.SUBMIT_ERROR, payload: true});
}
}
// Some Feature Saga that contains multiple sagas
function* meetingSaga() {
yield debounce(500, ActionTypes.HANDLE_SUBMIT, submit)
}tags: react redux redux-saga
sources: