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, on Hexlet, in every lesson, there is a discussion section where questions can be asked. This part of the frontend 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);
};

Exactly the same code will be used 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 work properly
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 4 lines in the reducers, and it brought us a full implementation of standard operations on the user. But that's 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 users slice, 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
  // 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 entities
  • selectById(state, id) – returns a specific entity or undefined if nothing is found

    // id – some kind of identifier
    const user = useSelector((state) => selectors.selectById(state, id));
    

Recommended materials

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

Hexlet Experts

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

From a novice to a developer. Get a job or your money back!

Frontend Developer icon
Profession
beginner
Development of front-end components for web applications
start anytime 10 months

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.