I have this react app, where i used to write redux code in an old way, i used redux and redux-thunk, but, updating this packages to newer version, i had this warning where the function that i used to create my store in the app just became deprecated, and they recommended to migrate to RTK.
But, after changing all the major stuff to this new way of writing redux, everything became slower, multiple actions are taking more time to get done, and that is impacting the UI, which feels uncomfortable.
So, i want to show you the way i'm writing my actions, my reducers, how i'm updating data and pretty much how i've done everything.
This is the store/config
import { configureStore } from '@reduxjs/toolkit';
import { useDispatch } from 'react-redux';
import reducers from './reducers';
export const storeConfig = configureStore({
reducer: reducers,
devTools: true,
});
// Types for dispatching actions and store's data itself
type AppDispatch = typeof storeConfig.dispatch;
export type reducersType = ReturnType<typeof reducers>;
// Types for custom useDispatch
export const useTypedDispatch = () => useDispatch<AppDispatch>();
These are my reducers
import { combineReducers } from '@reduxjs/toolkit';
import layout from './layoutReducer';
import pickupsNoAssign from './pickupsNoAssignReducer';
const reducers = combineReducers({ layout, pickupsNoAssign });
export default reducers;
This is my layout reducer with his actions
export interface ILayoutInitialState {
authentication?: IAuthentication;
authorizations?: IAuthorizations;
applicationOption?: IAppOptionsPayload;
isLeftDrawerOpen: boolean;
terminalSeleccionada?: string | number;
terminalNumber?: number;
serverError: string;
}
const initialState: ILayoutInitialState = {
isLeftDrawerOpen: true,
serverError: '',
};
const layoutReducer = createSlice({
name: layout,
initialState,
reducers: {
selectedTerminal: (state, { payload: { id, terminal } }: PayloadAction<ISelectedTerminalPayload>) => {
state.terminalSeleccionada = terminal;
state.terminalNumber = id;
},
selectedAppOption: (state, { payload }: PayloadAction<IAppOptionsPayload>) => {
state.applicationOption = payload;
},
leftDrawerAction: (state) => {
return {
...state,
isLeftDrawerOpen: !state.isLeftDrawerOpen,
};
},
},
extraReducers: (builder) => {
// authenticating
builder.addCase(authenticating.fulfilled, (state, { payload }) => {
const isThereToken = localStorage.getItem('accessToken');
if (!isThereToken) {
localStorage.setItem('accessToken', JSON.stringify({ ...payload.token }));
}
state.authentication = payload?.token;
state.authorizations = payload.data;
state.applicationOption = payload.appSelected;
state.terminalSeleccionada = `${payload?.token.terminal}-${payload?.token.abreviado}`;
state.terminalNumber = payload?.token.terminal;
});
builder.addCase(authenticating.rejected, (state, { payload }) => {
state.serverError = payload?.errorMessage!;
});
},
});
export const { selectedTerminal, selectedAppOption, leftDrawerAction } = layoutReducer.actions;
export default layoutReducer.reducer;
import { createAsyncThunk } from '@reduxjs/toolkit';
import {
ITerminales,
IAuthenthicatingParameters,
IAuthenthicatingPayload,
} from '../../domain/entities/redux/interfaceLayout';
import { layout } from '../../domain/helpers/types';
import { gettingPermission } from '../../infrastructure/services/api/layout/appPermissions';
// Validating authorizations
export const authenticating = createAsyncThunk<
IAuthenthicatingPayload,
IAuthenthicatingParameters,
{
rejectValue: { errorMessage: string };
}
>(`${layout}/authenticating`, async ({ token, navigate, goTo }, { rejectWithValue }) => {
try {
const data = await gettingPermission(token);
if (data && data.isError !== true && data.response !== null) {
// Selecting default app option
const optionTitle = data.response[0].permisos.aplicaciones.find(
(single) => single.id === 'sigo-distribucion',
)?.menus[0].nombre;
const optionApp = data.response[0].permisos.aplicaciones.find((single) => single.id === 'sigo-distribucion')
? data.response[0].permisos.aplicaciones.find((single) => single.id === 'sigo-distribucion')!.menus[0]
.sub_menu![0].nombre
: undefined;
// Adding default terminal
const addDefaultTerminal: ITerminales = { id: token.terminal, abreviatura: token.abreviado };
data.response[0].terminales.push(addDefaultTerminal);
navigate(goTo);
return { token, data, appSelected: { optionTitle, optionApp } };
}
} catch (err) {
console.log(err);
}
return rejectWithValue({ errorMessage: 'Hubo un fallo al obtener los permisos' });
});
I'm pretty much saving user data, and manipulating some options in the UI.
Am i updating the state with bad practices ? Am i writing my actions/api calls (with createAsyncThunk) wrong ?
What could be causing such behavior ?
CodePudding user response:
As mentioned RTK actually adds immutability and serializability checks: https://redux-toolkit.js.org/api/getDefaultMiddleware
This is very likely the root cause of the delay, I have experience with the immutability check and it can take tens of seconds to validate some very large stores.
RTK claim that the checks are not enabled in production mode, however, if you want to disable them completely do the following (code snipped from the above link some small modification):
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: true,
serializableCheck: false,
immutableCheck: false,
}),
})