Blog>
Snippets

Slicing State with createEntityAdapter in RTK 2.0

Showcase the usage of `createEntityAdapter` for normalized state shape and its new features introduced in RTK 2.0.
// Import createEntityAdapter from Redux Toolkit
import { createEntityAdapter } from '@reduxjs/toolkit';

// Define a user entity
const usersAdapter = createEntityAdapter();

// Initially, createEntityAdapter provides a set of generated selectors and reducers
// that we can use to manage the normalized state.
This piece of code imports the 'createEntityAdapter' function from Redux Toolkit and defines an entity adapter for users. It also mentions that by using this adapter we get a set of default selectors and reducers.
// Create slice with the entity adapter
import { createSlice } from '@reduxjs/toolkit';

// Define the initial state using the getInitialState method
const initialState = usersAdapter.getInitialState();

// Create a slice that includes the generated reducers from the adapter
const usersSlice = createSlice({
  name: 'users',
  initialState,
  reducers: {
    // Reducers will go here
  },
  extraReducers: {
    // Extra reducers can respond to other actions types
  },
});

// Export the reducer
export default usersSlice.reducer;
This code snippet creates a Redux slice using 'createSlice' and initializes the state with 'usersAdapter.getInitialState()'. It sets up a place for custom reducers and extra reducers that can be added separately.
// Use the created selectors
const {
  selectById: selectUserById,
  selectIds: selectUserIds,
  selectEntities: selectUserEntities,
  selectAll: selectAllUsers,
  selectTotal: selectTotalUsers
} = usersAdapter.getSelectors(state => state.users);

// Then, you can use these selectors like so to get data from your store
// const user = selectUserById(state, userId);
// const users = selectAllUsers(state);
In this code, custom named selectors are created using the adapter's 'getSelectors' method. It demonstrates how to retrieve the generated selectors and then use them to select data from the store.
// Add a new user with the 'addOne' reducer
// Assuming this is an action payload
const userToAdd = { id: '1', name: 'John Doe' };

// Later, in a reducer or a middleware:
// dispatch(usersSlice.actions.addOne(userToAdd));
This snippet shows how to add an entity to the state using the 'addOne' reducer generated by the entity adapter. 'userToAdd' is a new user object that should be dispatched as an action.
// Update a user with the 'updateOne' reducer
const userUpdate = { id: '1', changes: { name: 'Jane Doe' } };

// In a reducer or middleware, you would dispatch the update action
// dispatch(usersSlice.actions.updateOne(userUpdate));
Here is a demonstration of updating an entity using the 'updateOne' reducer. It requires an object with an 'id' and 'changes' object, and it is dispatched as an action.
// Remove a user with the 'removeOne' reducer
const userIdToRemove = '1';

// This action is dispatched to remove a user by their ID
// dispatch(usersSlice.actions.removeOne(userIdToRemove));
This example illustrates how to remove an entity from the store using the 'removeOne' reducer. The reducer takes an entity ID to locate and remove the entity from the state.