Blog>
Snippets

Implementing the Entity Adapter for Normalizing State

Walk through the process of migrating a manually managed normalized state to using the createEntityAdapter API from Redux Toolkit 2.0, focusing on CRUD operations.
import { createSlice, createEntityAdapter } from '@reduxjs/toolkit';

// Define a type for the slice state
interface UserState {
  ids: string[];
  entities: Record<string, UserType>;
}

// Create an entity adapter
const userAdapter = createEntityAdapter<UserType>();

// Define the initial state using the adapter's getInitialState method
const initialState = userAdapter.getInitialState();

// Define the slice
const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    // Reducer handlers using the adapter's methods for easy CRUD operations
    addUser: userAdapter.addOne,
    addUsers: userAdapter.addMany,
    updateUser: userAdapter.updateOne,
    removeUser: userAdapter.removeOne
  }
});

export const { addUser, addUsers, updateUser, removeUser } = userSlice.actions;

export default userSlice.reducer;
This code sets up a Redux slice using createEntityAdapter from Redux Toolkit 2.0 to normalize and manage the state for user entities. It defines a type for the slice state, creates an entity adapter with initial state, defines the slice with CRUD operation reducers using adapter methods, and exports the actions and reducer.
import { configureStore } from '@reduxjs/toolkit';
import userReducer from './userSlice';

// Configure the store with the userReducer
const store = configureStore({
  reducer: {
    user: userReducer
  }
});

export default store;
This code creates the Redux store and configures it with the user reducer created from the previous userSlice.
import { useSelector, useDispatch } from 'react-redux';
import { addUser, updateUser, removeUser } from './userSlice';

// Dispatch actions with the useDispatch hook
const dispatch = useDispatch();
dispatch(addUser({ id: '1', name: 'John Doe' }));
dispatch(updateUser({ id: '1', changes: { name: 'Jane Doe' } }));
dispatch(removeUser('1'));

// Access normalized state with the useSelector hook
const users = useSelector(state => state.user.entities);
This code demonstrates how to dispatch actions and access the normalized state in a React component using the hooks from react-redux.
<!-- HTML -->
<div id='app'></div>
This is the HTML markup with a root div where the React application will be mounted.
/* CSS */
#app {
  margin: 20px;
  font-family: Arial, sans-serif;
}
This is the CSS style for the root div of the app.