Blog>
Snippets

Debouncing User Input with Redux Saga

Illustrate the implementation of a debounce effect in Redux Saga to handle rapid, successive actions, such as those triggered by typing in a search field.
// sagaActions.js
export const sagaActions = {
  SEARCH_USER_INPUT: 'SEARCH_USER_INPUT',
  DEBOUNCED_SEARCH: 'DEBOUNCED_SEARCH'
};
Defines the action types for initiating search and the debounced search.
// searchSaga.js
import { debounce, put, call } from 'redux-saga/effects'
import { sagaActions } from './sagaActions';
import Axios from 'axios';

function* fetchSearchResults(action) {
  try {
    const response = yield call(Axios.get, `https://yourapi.com/search?q=${action.payload}`);
    yield put({ type: 'SEARCH_RESULTS', payload: response.data });
  } catch (e) {
    // handle error
  }
}

export function* watchSearchInput() {
  yield debounce(500, sagaActions.SEARCH_USER_INPUT, fetchSearchResults);
}
Watches for SEARCH_USER_INPUT actions and debounces them. After 500ms of inactivity on this action, it calls fetchSearchResults saga with the action.
// rootSaga.js
import { all, fork } from 'redux-saga/effects';
import { watchSearchInput } from './searchSaga';

export default function* rootSaga() {
  yield all([
    fork(watchSearchInput)
  ]);
}
Includes the watchSearchInput saga in the root saga. This setup is necessary to start the saga within the Redux-Saga middleware environment.
// store.js
import { configureStore } from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas/rootSaga';

const sagaMiddleware = createSagaMiddleware();
const store = configureStore({
  reducer: {
    // your reducers
  },
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(sagaMiddleware)
});
sagaMiddleware.run(rootSaga);

export default store;
Creates the Redux store, adds the Redux-Saga middleware, and runs the rootSaga which contains our debounce logic for search input.