Значительная часть любого веб-приложения сводится к операциям над какими-то сущностями, их добавлению, изменению, удалению и чтению. Например, на Хекслете, в каждом уроке, есть раздел обсуждений, там где задаются вопросы. Эта часть фронтенда работает с постами, комментариями, авторами и лайками. Благодаря нормализации данных, код по обработке этих сущностей выглядит идентично:
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);
};
Точно такой же код будет использоваться и для всех остальных сущностей. Можно ли как-то переиспользовать его? Конечно! Redux Toolkit делает это с помощью механизма Entity Adapter. Он предоставляет набор готовых редьюсеров и селекторов для основных операций над сущностями. Сначала пример:
import {
createSlice,
createEntityAdapter,
} from '@reduxjs/toolkit';
const usersAdapter = createEntityAdapter();
// По умолчанию: { 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,
},
});
// Где-то в приложении
// По соглашению, в передаваемых данных должен быть id для правильной работы
dispatch(addUser(user));
// Данные передаются в формате: { id, changes }
dispatch(updateUser({ id: user.id, changes: data }));
// Достаточно передать идентификатор
dispatch(removeUser(user.id));
Буквально 4 строчки в редьюсерах и мы получили полноценную реализацию стандартных операций над пользователем. Но это еще не все, кроме готовых редьюсеров, Entity Adapter дает нам набор готовых селекторов для извлечения данных из хранилища. Для этого их нужно сгенерировать и экспортировать из файла со слайсом:
// file: usersSlice.js
// Колбек определяет базовый селектор, извлекающий нужную часть состояния из Redux
// Для слайса users это state.users
export const selectors = usersAdapter.getSelectors((state) => state.users);
Пример использования в приложении:
import { useSelector, useDispatch } from 'react-redux';
import { selectors } from '../slices/usersSlice.js';
const MyComponent = (props) => {
// Извлекаем всех пользователей в виде массива
// Внутри происходит выборка данных из state.users.entities
// отсортированная по state.users.ids
const users = useSelector(selectors.selectAll);
// тут логика вывода
}
Кроме selectAll(state)
мы получаем:
selectIds(state)
– возвращает ids
selectEntities(state)
– возвращает entities
selectTotal(state)
– возвращает общее количествоselectById(state, id)
– возвращает конкретную сущность или undefined
если ничего не найдено
// id – какой-то идентификатор
const user = useSelector((state) => selectors.selectById(state, id));
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Статья «Ловушки обучения»
Вебинар «Как самостоятельно учиться»
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт