Этот вопрос проверяет знание техник оптимизации в Redux, в частности, мемоизации селекторов для предотвращения избыточных перевычислений производных данных.
Чтобы замемоизировать вызов селектора в Redux, используется библиотека Reselect. Она позволяет создавать "мемоизированные" селекторы, которые пересчитывают свое значение только тогда, когда изменяются входные данные (аргументы) селектора. Если аргументы остались прежними, селектор возвращает закешированный результат, что предотвращает дорогостоящие вычисления и лишние ре-рендеры компонентов.
Мемоизация — это техника оптимизации, которая кеширует результаты дорогих вызовов функций.
Представьте селектор, который фильтрует и сортирует большой список:
const getVisibleTodos = (state) => {
// Это вычисление выполняется при КАЖДОМ вызове селектора,
// даже если `state.todos` и `state.visibilityFilter` не изменились.
const { todos, visibilityFilter } = state;
return todos.filter(todo => {
switch (visibilityFilter) {
case 'SHOW_COMPLETED':
return todo.completed;
case 'SHOW_ACTIVE':
return !todo.completed;
default:
return true;
}
});
};Если компонент соединяется с хранилищем с помощью connect, этот селектор будет запускаться при каждом обновлении состояния Redux, даже если это обновление не связано с todos или visibilityFilter.
Reselect предоставляет функцию createSelector для создания мемоизированных селекторов.
Установите Reselect: npm install reselect
Создайте мемоизированный селектор:
javascript
import { createSelector } from 'reselect';
// Простые селекторы, которые просто извлекают кусок состояния
const getTodos = state => state.todos;
const getVisibilityFilter = state => state.visibilityFilter;
// Мемоизированный селектор
export const getVisibleTodos = createSelector(
[getTodos, getVisibilityFilter], // Массив входных селекторов
(todos, visibilityFilter) => { // Функция-трансформер
// Дорогое вычисление выполнится ТОЛЬКО если todos или visibilityFilter изменились
return todos.filter(todo => {
switch (visibilityFilter) {
case 'SHOW_COMPLETED':
return todo.completed;
case 'SHOW_ACTIVE':
return !todo.completed;
default:
return true;
}
});
}
);При первом вызове getVisibleTodos(state) Reselect запускает функцию-трансформер и кеширует результат. При последующих вызовах он сначала проверяет, изменились ли результаты getTodos(state) и getVisibilityFilter(state). Если нет — возвращает кешированное значение.
Используйте Reselect для мемоизации селекторов, которые выполняют сложные вычисления или производные преобразования над состоянием. Это значительно повышает производительность, особенно в больших приложениях, сокращая количество ненужных вычислений и ре-рендеров связанных компонентов.