VOOZH about

URL: https://www.javacodegeeks.com/2025/06/managing-state-in-react-with-redux-toolkit-advanced-patterns.html

⇱ Managing State in React with Redux Toolkit: Advanced Patterns - Java Code Geeks


Redux Toolkit (RTK) has revolutionized state management in React applications by reducing boilerplate and providing sensible defaults. While basic usage is straightforward, mastering advanced patterns can elevate your state management to production-grade quality. Here’s a deep dive into professional techniques used by top React developers.

1. Dynamic Reducer Injection

Problem:

Loading all reducers upfront hurts performance in large apps

Solution:

// store.js
import { configureStore } from '@reduxjs/toolkit'
import { createReducerManager } from './reducerManager'

const staticReducers = {
 users: usersReducer,
 auth: authReducer
}

export function setupStore(initialState) {
 const reducerManager = createReducerManager(staticReducers)
 
 const store = configureStore({
 reducer: reducerManager.reduce,
 preloadedState: initialState
 })

 store.reducerManager = reducerManager
 return store
}

// reducerManager.js
export function createReducerManager(initialReducers) {
 const reducers = { ...initialReducers }
 let combinedReducer = combineReducers(reducers)
 let keysToRemove = []

 return {
 reduce: (state, action) => {
 if (keysToRemove.length > 0) {
 state = { ...state }
 keysToRemove.forEach(key => delete state[key])
 keysToRemove = []
 }
 return combinedReducer(state, action)
 },
 add: (key, reducer) => {
 reducers[key] = reducer
 combinedReducer = combineReducers(reducers)
 },
 remove: key => {
 keysToRemove.push(key)
 delete reducers[key]
 }
 }
}

Usage in Components:

useEffect(() => {
 store.reducerManager.add('dynamicFeature', dynamicReducer)
 return () => {
 store.reducerManager.remove('dynamicFeature')
 }
}, [])

2. Normalized State with Entity Adapter

Problem:

Nested/denormalized state causes performance issues

Solution:

import { createEntityAdapter } from '@reduxjs/toolkit'

const usersAdapter = createEntityAdapter({
 selectId: user => user.id,
 sortComparer: (a, b) => a.name.localeCompare(b.name)
})

const usersSlice = createSlice({
 name: 'users',
 initialState: usersAdapter.getInitialState(),
 reducers: {
 userAdded: usersAdapter.addOne,
 userUpdated: usersAdapter.updateOne,
 userRemoved: usersAdapter.removeOne,
 usersReceived(state, action) {
 usersAdapter.setAll(state, action.payload)
 }
 }
})

// Selectors
export const {
 selectAll: selectAllUsers,
 selectById: selectUserById,
 selectIds: selectUserIds
} = usersAdapter.getSelectors(state => state.users)

Benefits:

  • Automatic memoization
  • Optimized updates
  • Built-in CRUD operations

3. Advanced Middleware Patterns

Action Sequencing

const sequenceMiddleware = storeAPI => next => action => {
 if (action.meta?.sequenceId) {
 const state = storeAPI.getState()
 const lastSequence = state.lastSequenceId || 0
 
 if (action.meta.sequenceId <= lastSequence) {
 return // Ignore out-of-order actions
 }
 }
 return next(action)
}

Optimistic Updates with Rollback

import { createAsyncThunk, nanoid } from '@reduxjs/toolkit'

const updateUser = createAsyncThunk(
 'users/update',
 async (userData, { dispatch, getState }) => {
 const transactionId = nanoid()
 
 dispatch({
 type: 'users/optimisticUpdate',
 payload: { ...userData, pending: true },
 meta: { transactionId }
 })

 try {
 const response = await api.updateUser(userData)
 return { ...response, transactionId }
 } catch (error) {
 return { error, transactionId }
 }
 },
 {
 condition: (_, { getState }) => {
 const { isUpdating } = getState().users
 return !isUpdating // Skip if already updating
 }
 }
)

// In extraReducers:
.addCase(updateUser.fulfilled, (state, action) => {
 const { transactionId, ...user } = action.payload
 usersAdapter.updateOne(state, {
 id: user.id,
 changes: { ...user, pending: false }
 })
})
.addCase(updateUser.rejected, (state, action) => {
 const { transactionId } = action.meta.arg
 // Rollback logic
})

4. Selector Memoization Patterns

Reselect with RTK

import { createSelector } from '@reduxjs/toolkit'

const selectUsers = state => state.users.entities
const selectActiveFilter = state => state.users.activeFilter

export const selectFilteredUsers = createSelector(
 [selectUsers, selectActiveFilter],
 (users, filter) => {
 return users.filter(user => 
 filter === 'all' || user.status === filter
 )
 }
)

Dynamic Selector Factory

export const makeSelectUserById = () => 
 createSelector(
 [selectUsers, (_, id) => id],
 (users, id) => users[id]
 )

// Usage:
const selectUser = makeSelectUserById()
const user = useSelector(state => selectUser(state, userId))

5. Server-State Synchronization with RTK Query

Advanced Cache Management

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

const api = createApi({
 reducerPath: 'api',
 baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
 tagTypes: ['User', 'Post'],
 endpoints: builder => ({
 getUsers: builder.query({
 query: () => 'users',
 providesTags: ['User']
 }),
 updateUser: builder.mutation({
 query: ({ id, ...patch }) => ({
 url: `users/${id}`,
 method: 'PATCH',
 body: patch
 }),
 invalidatesTags: (result, error, { id }) => [
 { type: 'User', id },
 'Post' // Also invalidate all posts
 ],
 onQueryStarted: async (arg, { dispatch, queryFulfilled }) => {
 // Optimistic update
 const patchResult = dispatch(
 api.util.updateQueryData('getUser', arg.id, draft => {
 Object.assign(draft, arg)
 })
 )
 try {
 await queryFulfilled
 } catch {
 patchResult.undo() // Rollback
 }
 }
 })
 })
})

6. State Persistence Strategies

Rehydration with Redux-Persist

import { persistReducer, persistStore } from 'redux-persist'
import storage from 'redux-persist/lib/storage'

const persistConfig = {
 key: 'root',
 storage,
 whitelist: ['auth'],
 transforms: [encryptTransform] // For sensitive data
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

export const store = configureStore({
 reducer: persistedReducer,
 middleware: getDefaultMiddleware =>
 getDefaultMiddleware({
 serializableCheck: {
 ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
 }
 })
})

export const persistor = persistStore(store)

Differential Persistence

const advancedPersistConfig = {
 key: 'userSettings',
 storage,
 serialize: data => {
 const { temporary, ...persistent } = data
 return JSON.stringify(persistent)
 },
 deserialize: str => {
 const persistent = JSON.parse(str)
 return { ...persistent, temporary: {} }
 }
}

7. Testing Strategies

Middleware Testing

test('auth middleware processes token', () => {
 const store = mockStore({})
 const next = jest.fn()
 const action = { type: 'LOGIN', payload: { token: 'abc123' } }

 authMiddleware(store)(next)(action)

 expect(localStorage.setItem).toHaveBeenCalledWith('token', 'abc123')
 expect(next).toHaveBeenCalledWith(action)
})

Reducer Composition Testing

describe('nested reducers', () => {
 let store
 
 beforeEach(() => {
 store = setupStore()
 store.reducerManager.add('dynamicFeature', dynamicReducer)
 })

 test('handles cross-slice actions', () => {
 store.dispatch({ type: 'TRIGGER_UPDATE' })
 expect(store.getState().dynamicFeature).toEqual(/* expected */)
 })
})

Key Takeaways

  1. Dynamic injection enables code splitting for reducers
  2. Entity adapter solves normalization challenges
  3. Middleware patterns handle complex side effects
  4. Advanced selectors optimize performance
  5. RTK Query simplifies server state management
  6. Persistence strategies balance UX and security
  7. Testing techniques ensure reliability

These patterns represent professional-grade Redux architecture used in large-scale applications. Implement them progressively as your application’s complexity grows.

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

πŸ‘ Photo of Eleftheria Drosopoulou
Eleftheria Drosopoulou
June 20th, 2025Last Updated: June 13th, 2025
0 1,110 4 minutes read

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz