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: