Saga to Listeners
A comprehensive guide for migrating to the new listeners architecture
highlighting key concepts and differences in implementation:
Setupping the Configs
// src/app/createAppSelector.ts
import { createSelector } from '@reduxjs/toolkit';
import { RootState } from './store';
export const createAppSelector = createSelector.withTypes<RootState>();
// src/app/createAppSlice.ts
import {
asyncThunkCreator,
buildCreateSlice,
} from '@reduxjs/toolkit';
export const createAppSlice = buildCreateSlice({
creators: { asyncThunk: asyncThunkCreator },
});
// src/app/listener.ts
import { createListenerMiddleware } from '@reduxjs/toolkit';
import type {
AppDispatch,
RootState,
} from './store';
export const listener = createListenerMiddleware();
/**
* Function to start listening for actions
*/
export const startAppListening = listener.startListening.withTypes<
RootState,
AppDispatch
>();
Understanding the Migration
The main differences between Sagas and Listeners involve how we handle side effects and state management:
call→ Direct function callsput→listenerApi.dispatch- Saga generators → Listener effect callbacks
select→listenerApi.getState
Code Comparison
/**
* Get device from Glados
*/
export function* getDeviceSaga(): Generator<StrictEffect> {
const hardwareService = GladosServiceFactory.getHardwareService();
try {
const response =
(yield call([hardwareService, hardwareService.getHardwareDetailGroup], 'v1', params)) as
Awaited<ReturnType<typeof hardwareService.getHardwareDetailGroup>>;
const { data } = response;
yield put(getDeviceSuccess(data));
}
catch (error: any) {
yield call([console, 'error'], error);
const { response } = error;
if (response && response.status === 404) {
yield call(redirectToDop);
} else {
yield put(getDeviceFailed());
}
}
}
/**
* Get device success saga
*/
export function* getDeviceSuccessSaga(): Generator<StrictEffect> {
const atomicId = (yield select(selectAtomicId())) as SelectorReturnType<typeof selectAtomicId>;
yield put(setAtomicId(atomicId!));
yield put(getSubscriptions());
}
Key Concepts in Listeners
-
Action Creation and Dispatch
- Instead of using
puteffects like in Sagas, Listeners uselistenerApi.dispatch - Actions are dispatched directly without needing to yield
- Instead of using
-
State Management
- Replace
selecteffects withlistenerApi.getState() - Access state directly through the listener API
- Replace
-
Effect Handling
- Replace generator functions with effect callbacks
- Use
startAppListeningto register listeners - Handle success and error cases with separate listeners using
matcher