Code Example 1: Problem without selectors
❓ Какая проблема возникает, когда компоненты напрямую обращаются к структуре state?
const user = state.entities.users.byId[userId];
const posts = state.entities.posts.list.filter(p => p.authorId === userId);
Code Example 2: Basic selectors
❓ Что такое input selector? Какие преимущества даёт использование селекторов?
const selectUsers = (state: RootState) => state.users;
const selectPosts = (state: RootState) => state.posts;
const selectCurrentUserId = (state: RootState) => state.auth.currentUserId;
Code Example 3: Selectors with parameters
❓ Как создать селектор с параметром? Объясните работу selectUserById.
export const selectUsersState = (state: RootState) => state.users;
export const selectAllUsers = (state: RootState) =>
Object.values(state.users.byId);
export const selectUserById = (state: RootState, userId: string) =>
state.users.byId[userId];
export const selectUsersLoading = (state: RootState) =>
state.users.status === 'loading';
Code Example 4: useSelector with selectors
❓ Как использовать селекторы с useSelector? Почему передаём функцию внутрь useSelector?
import { useSelector } from 'react-redux';
import { selectUserById, selectUsersLoading } from './selectors';
function UserProfile({ userId }: { userId: string }) {
const user = useSelector((state: RootState) =>
selectUserById(state, userId)
);
const isLoading = useSelector(selectUsersLoading);
if (isLoading) return <Spinner />;
if (!user) return <NotFound />;
return <div>{user.name}</div>;
}
Code Example 5: Memoized selectors with createSelector
❓ Зачем нужна мемоизация в селекторах? Когда selectCurrentUserPosts будет пересчитан?
import { createSelector } from '@reduxjs/toolkit';
const selectPosts = (state: RootState) => state.posts.items;
const selectCurrentUserId = (state: RootState) => state.auth.userId;
export const selectCurrentUserPosts = createSelector(
[selectPosts, selectCurrentUserId],
(posts, userId) => {
console.log('Пересчёт селектора');
return posts.filter(post => post.authorId === userId);
}
);
Code Example 6: Selector composition
❓ Как работает композиция селекторов? Что происходит при изменении selectUsers?
const selectUsers = (state: RootState) => state.users.byId;
const selectPosts = (state: RootState) => state.posts.items;
export const selectPostsWithAuthors = createSelector(
[selectPosts, selectUsers],
(posts, users) =>
posts.map(post => ({
...post,
author: users[post.authorId],
}))
);
export const selectPublishedPostsWithAuthors = createSelector(
[selectPostsWithAuthors],
(posts) => posts.filter(post => post.status === 'published')
);
Code Example 7: Parameterized selectors problem
❓ Почему этот селектор неэффективен при вызове с разными userId? Как решить эту проблему?
const selectUserById = createSelector(
[selectUsers, (_, userId: string) => userId],
(users, userId) => users[userId]
);
Code Example 8: Selector factory pattern
❓ Что такое фабрика селекторов? Зачем каждому компоненту нужен свой экземпляр?
const makeSelectUserById = () =>
createSelector(
[selectUsers, (_, userId: string) => userId],
(users, userId) => users[userId]
);
const selectUser = useMemo(makeSelectUserById, []);