API Migration Guide
A comprehensive guide that covers the migration process to the new API implementation.
focusing on two main aspects:
- Forming the API 2. Using the API
Forming the API
/**
* Get device from Glados
*/
export function* getDeviceSaga(): Generator<StrictEffect> {
const hardwareService = GladosServiceFactory.getHardwareService();
// Collecting data to make the api request
try {
const response = (yield call([hardwareService, hardwareService.getHardwareDetailGroup], 'v1', params)) as Awaited<ReturnType<typeof hardwareService.getHardwareDetailGroup>>;
const { data } = response;
// Side effects handled by listeners
} catch (error: any) {
// Side effects handled by listeners
}
}
/**
* Get subscription from Glados
*/
export function* getSubscriptionsSaga(): Generator<StrictEffect> {
const tariffService = GladosServiceFactory.getTariffService();
// Collecting data to make the api request
try {
const response = (yield call([tariffService, tariffService.getTariffWithHardware], 'v1', params)) as Awaited<ReturnType<typeof tariffService.getTariffWithHardware<RedTariff | YoungTariff>>>;
const { data } = response;
// Side effects handled by listeners
} catch (error) {
// Side effects handled by listeners
}
}
Using the API
In Selectors
The new API can be used with selectors to dynamically update state. Here's how to implement selectors with the API:
/**
* Selects the HardwareDetailGroup query selector
*/
const createHardwareDetailGroupSelector = createAppSelector(
[
state => state.vvlDeviceDetailsApp.salesChannel,
],
salesChannel => getHardwareDetailGroup.select({
salesChannel: salesChannel!,
}),
);
/**
* Selects the HardwareDetailGroup query
*/
const selectHardwareDetailGroupQuery = createAppSelector(
[
state => state,
createHardwareDetailGroupSelector,
],
(state, selector) => selector(state),
);
/**
* Selects the full device
*/
const selectDevice = createAppSelector(
[
selectHardwareDetailGroupQuery,
],
query => query?.data || null,
);
In Listeners
Listeners are used to perform side effects in response to API actions:
setDefaultState: () => startAppListening({
actionCreator: setDefaultState,
effect: (_action, listenerApi) => {
// rest of the side effects
deviceId
? listenerApi.dispatch(getHardwareDetailGroup.initiate({ salesChannel }))
: redirectToDop();
},
}),
getDeviceFulfilled: () => startAppListening({
matcher: getHardwareDetailGroup.matchFulfilled,
effect: (_action, listenerApi) => {
// rest of the side effects
listenerApi.dispatch(getTariffWithHardware.initiate({
salesChannel,
isTradeIn
}));
},
}),
In Extra Reducers
Extra reducers can be used to handle asynchronous logic without using createAsyncThunk:
extraReducers: builder => {
builder
.addMatcher(
getHardwareDetailGroup.matchFulfilled,
(state, action) => {
const { atomics } = action.payload.data;
if (
!state.atomicId ||
!atomics.some(atomic => atomic.hardwareId === state.atomicId)
) {
const defaultAtomic = atomics.find(
atomic => atomic.defaultAtomicDevice
);
state.atomicId = defaultAtomic?.hardwareId || null;
}
const currentAtomic = atomics.find(
item => item.hardwareId === state.atomicId
);
state.currentColor = currentAtomic?.color || null;
state.currentCapacity = currentAtomic?.capacity || null;
},
)
}