Введение в Redux
Redux — это инструмент для управления состоянием приложения. Его можно представить как библиотеку (чем он, собственно, и является), которая позволяет удобно управлять состоянием, даже если приложение очень большое и сложное. Redux основывается на трех ключевых принципах:
- Единственный источник правды (Single Source of Truth): все состояние сохраняется в одном месте, известном как Store.
- Состояние неизменяемо (State is Read-Only): состояние нельзя изменить напрямую. Единственный способ изменить состояние — это отправить действие (action).
- Чистые функции (Pure Functions): для обновления состояния используются чистые функции, называемые редьюсерами (reducers).
Теперь попробуем объяснить это на простой аналогии. Представьте, что вы управляете огромным складом товаров (это ваше приложение). Каждое изменение состояния — это добавление/удаление товара, обновление цены или количества. Redux здесь играет роль администратора, который получает заявки (действия), обрабатывает их (редьюсеры) и обновляет состояние склада.
Redux придумал человек по имени Дэн Абрамов, который также участвовал в разработке React. Redux по сей день остается одним из самых популярных инструментов для управления состоянием в JavaScript.
Когда Redux действительно нужен?
Redux — это очень мощный, но не обязательный инструмент. У маленьких приложений с несколькими страницами или простым взаимодействием можно обойтись и без него. Но как только приложение начинает разрастаться, появляются следующие проблемы:
Многоуровневые вложенности состояний. Например, нужно передать состояние от компонента "родителя" через несколько "детей" к "внуку". Это может превратиться в "пропс-ад", когда приходится передавать данные через десятки уровней только ради одного компонента.
Сложная бизнес-логика. Например, пользователь заполняет форму через несколько шагов, при этом нужно сохранять промежуточные данные между шагами.
Отслеживание изменений. Как только состояние приложения становится сложным (например, несколько форм, работающих одновременно), легко запутаться в том, что и где изменилось.
Redux создан для работы с крупными и сложными приложениями. Его сила в том, что он позволяет удобно управлять глобальным состоянием и разделять код на логически обоснованные части.
Ключевые концепции Redux
1. Store — ваш хранилище
Store — это то самое место, где хранится все состояние вашего приложения. Если вы помните слова "единственный источник правды", то Store и есть эта "правда".
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: {}, // редьюсеры (о них чуть позже)
});
export default store;
На практике вы можете воспринимать Store как большой объект, который описывает текущее состояние вашего приложения.
2. Actions — отправляем запрос на изменения
Action — это объект, который описывает то, что мы хотим сделать. Например, если нужно добавить пользователя в список, создается action с соответствующими данными.
const addUser = {
type: 'ADD_USER',
payload: {
id: 1,
name: 'Алиса',
},
};
Здесь два ключевых свойства:
type: строка, описывающая тип действия (например, "ADD_USER").payload: объект с данными, которые нужны для выполнения действия.
3. Reducer — наш обработчик заявок
Reducer — это функция, которая принимает текущее состояние и action, а затем возвращает новое состояние. Ничего сложного, правда? Это другая аналогия нашего "администратора склада".
const initialState = { users: [] };
function userReducer(state = initialState, action) {
switch (action.type) {
case 'ADD_USER':
return {
...state,
users: [...state.users, action.payload],
};
default:
return state;
}
}
В данном примере редьюсер получает текущее состояние, проверяет action.type и, если это "ADD_USER", добавляет нового пользователя в массив users.
4. Dispatch — доставляем action в Store
Чтобы что-то изменилось в Store, нужно отправить action с помощью функции dispatch. Это как отправить заявку администратору.
store.dispatch(addUser);
Простой пример: счетчик
Давайте создадим минимальное приложение на Redux: простой счетчик, который увеличивается, уменьшается и сбрасывается к нулю.
Настройка Store
import { configureStore } from '@reduxjs/toolkit';
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
case 'RESET':
return { count: 0 };
default:
return state;
}
}
const store = configureStore({
reducer: counterReducer,
});
export default store;
Отправляем действия
Теперь отправим несколько действий, чтобы проверить, работает ли наш Store.
console.log(store.getState()); // { count: 0 }
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // { count: 1 }
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // { count: 2 }
store.dispatch({ type: 'DECREMENT' });
console.log(store.getState()); // { count: 1 }
store.dispatch({ type: 'RESET' });
console.log(store.getState()); // { count: 0 }
Да, это крайне базовый пример, но он позволяет понять принципы работы Redux.
Настоящий мир — сложнее
В реальной жизни никто не пишет такой код вручную (особенно с Redux Toolkit, где есть множество удобных функций). Помимо этого, нам нужно будет подключить Redux к нашим React-компонентам, чтобы все выглядело красиво и работало плавно.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ