Register to get access to free programming courses with interactive exercises

Entity Adapter React: Redux Toolkit

A big part of any web application comes down to operations on entities, adding, changing, deleting, and reading them. For example, in every Hexlet lesson, you can find a discussion section and ask some questions. This section of the front end handles posts, comments, authors, and likes. Thanks to data normalization, the code for processing these entities looks identical:

const addPost = (state, post) => {
  state.entities[post.id] = post;
  state.ids.push(post.id);
};

const addLike = (state, like) => {
  state.entities[like.id] = like;
  state.ids.push(like.id);
};

We will use the same code for all other entities. Is there any way to reuse it? Of course! Redux Toolkit does this using the Entity Adapter mechanism. It provides a set of ready-made reducers and selectors for basic entity operations. First, an example:

import {
  createSlice,
  createEntityAdapter,
} from '@reduxjs/toolkit';

const usersAdapter = createEntityAdapter();

// By default: { ids: [], entities: {} }
const initialState = usersAdapter.getInitialState();

const slice = createSlice({
  name: 'users',
  initialState,
  reducers: {
    addUser: usersAdapter.addOne,
    addUsers: usersAdapter.addMany,
    removeUser: usersAdapter.removeOne,
    updateUser: usersAdapter.updateOne,
  },
});

// Somewhere in the application

// By convention, the passed data must have an `id` in it to properly work
dispatch(addUser(user));
// The data are transmitted in this format: { id, changes }
dispatch(updateUser({ id: user.id, changes: data }));
// It's enough to pass the identifier
dispatch(removeUser(user.id));

Just four lines in the reducers brought us a full implementation of standard operations on the user. But that is not all. Besides ready-made reducers, Entity Adapter gives us a set of ready-made selectors to retrieve data from the store. To do this, they must be generated and exported from the file with the slice:

// file: usersSlice.js

// Callback defines a basic selector that extracts the desired part of the state from Redux
// For the `usersSlice`, it's `state.users`
export const selectors = usersAdapter.getSelectors((state) => state.users);

Example of its use in the application:

import { useSelector, useDispatch } from 'react-redux';

import { selectors } from '../slices/usersSlice.js';

const MyComponent = (props) => {
  // Retrieving all users as an array
  // The data from `state.users.entities` is selected internally
  // And it is sorted by `state.users.ids`
  const users = useSelector(selectors.selectAll);

  // Here's the logic of the output
}

In addition to the selectAll(state) we get:

  • selectIds(state) – returns ids
  • selectEntities(state) – returns entities
  • selectTotal(state) – returns the total amount
  • selectById(state, id) – returns a specific entity or undefined if it found nothing

    // The `id` is some identifier
    const user = useSelector((state) => selectors.selectById(state, id));
    

Recommended materials

  1. What is CRUD?
  2. The documentation of `createEntityAdapter`
  3. Creating Your Own Selectors

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.