Redux решает проблему управления состоянием в больших приложениях:
Всё состояние приложения хранится в одном объекте — store:
const state = {
user: { name: 'Алексей', role: 'admin' },
todos: [{ id: 1, text: 'Изучить Redux', done: false }],
ui: { theme: 'dark', sidebarOpen: true }
}Единственный способ изменить состояние — отправить action (экшен):
// Action — простой объект с полем type
const action = {
type: 'todos/add',
payload: { id: 2, text: 'Практика Redux', done: false }
}
// Отправляем экшен в store
store.dispatch(action)Изменения обрабатываются чистыми функциями — reducers (редьюсеры):
function todosReducer(state = [], action) {
switch (action.type) {
case 'todos/add':
return [...state, action.payload]
case 'todos/toggle':
return state.map(todo =>
todo.id === action.payload
? { ...todo, done: !todo.done }
: todo
)
default:
return state
}
}UI → dispatch(action) → Reducer → New State → UI обновляется1. Пользователь кликает кнопку
2. Компонент вызывает dispatch({ type: 'counter/increment' })
3. Redux передаёт экшен в редьюсер
4. Редьюсер возвращает новое состояние
5. Store уведомляет подписчиков
6. React перерисовывает компоненты с новыми данными
import { createStore } from 'redux'
// Начальное состояние
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 'INCREMENT_BY':
return { count: state.count + action.payload }
default:
return state
}
}
// Создаём store
const store = createStore(counterReducer)
// Подписываемся на изменения
store.subscribe(() => {
console.log('State:', store.getState())
})
// Отправляем экшены
store.dispatch({ type: 'INCREMENT' }) // { count: 1 }
store.dispatch({ type: 'INCREMENT_BY', payload: 5 }) // { count: 6 }Много шаблонного кода:
Redux Toolkit решает эти проблемы — следующий урок.
Нужен Redux если:
Не нужен Redux если:
Принцип работы Redux: store, dispatch, subscribe
// Упрощённая реализация Redux для понимания концепции
function createStore(reducer) {
let state = reducer(undefined, { type: '@@INIT' })
const listeners = []
return {
getState() {
return state
},
dispatch(action) {
console.log('Dispatching:', action.type)
state = reducer(state, action)
listeners.forEach(listener => listener())
return action
},
subscribe(listener) {
listeners.push(listener)
return () => {
const index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
}
}
// Редьюсер для списка задач
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, { id: Date.now(), text: action.payload, done: false }]
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.payload ? { ...todo, done: !todo.done } : todo
)
case 'REMOVE_TODO':
return state.filter(todo => todo.id !== action.payload)
default:
return state
}
}
const store = createStore(todosReducer)
// Подписываемся на изменения
store.subscribe(() => {
console.log('Todos:', store.getState())
})
// Dispatch экшенов
store.dispatch({ type: 'ADD_TODO', payload: 'Изучить Redux' })
store.dispatch({ type: 'ADD_TODO', payload: 'Практика Redux Toolkit' })
const todos = store.getState()
store.dispatch({ type: 'TOGGLE_TODO', payload: todos[0].id })
console.log('Финальное состояние:', store.getState())Redux решает проблему управления состоянием в больших приложениях:
Всё состояние приложения хранится в одном объекте — store:
const state = {
user: { name: 'Алексей', role: 'admin' },
todos: [{ id: 1, text: 'Изучить Redux', done: false }],
ui: { theme: 'dark', sidebarOpen: true }
}Единственный способ изменить состояние — отправить action (экшен):
// Action — простой объект с полем type
const action = {
type: 'todos/add',
payload: { id: 2, text: 'Практика Redux', done: false }
}
// Отправляем экшен в store
store.dispatch(action)Изменения обрабатываются чистыми функциями — reducers (редьюсеры):
function todosReducer(state = [], action) {
switch (action.type) {
case 'todos/add':
return [...state, action.payload]
case 'todos/toggle':
return state.map(todo =>
todo.id === action.payload
? { ...todo, done: !todo.done }
: todo
)
default:
return state
}
}UI → dispatch(action) → Reducer → New State → UI обновляется1. Пользователь кликает кнопку
2. Компонент вызывает dispatch({ type: 'counter/increment' })
3. Redux передаёт экшен в редьюсер
4. Редьюсер возвращает новое состояние
5. Store уведомляет подписчиков
6. React перерисовывает компоненты с новыми данными
import { createStore } from 'redux'
// Начальное состояние
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 'INCREMENT_BY':
return { count: state.count + action.payload }
default:
return state
}
}
// Создаём store
const store = createStore(counterReducer)
// Подписываемся на изменения
store.subscribe(() => {
console.log('State:', store.getState())
})
// Отправляем экшены
store.dispatch({ type: 'INCREMENT' }) // { count: 1 }
store.dispatch({ type: 'INCREMENT_BY', payload: 5 }) // { count: 6 }Много шаблонного кода:
Redux Toolkit решает эти проблемы — следующий урок.
Нужен Redux если:
Не нужен Redux если:
Принцип работы Redux: store, dispatch, subscribe
// Упрощённая реализация Redux для понимания концепции
function createStore(reducer) {
let state = reducer(undefined, { type: '@@INIT' })
const listeners = []
return {
getState() {
return state
},
dispatch(action) {
console.log('Dispatching:', action.type)
state = reducer(state, action)
listeners.forEach(listener => listener())
return action
},
subscribe(listener) {
listeners.push(listener)
return () => {
const index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
}
}
// Редьюсер для списка задач
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, { id: Date.now(), text: action.payload, done: false }]
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.payload ? { ...todo, done: !todo.done } : todo
)
case 'REMOVE_TODO':
return state.filter(todo => todo.id !== action.payload)
default:
return state
}
}
const store = createStore(todosReducer)
// Подписываемся на изменения
store.subscribe(() => {
console.log('Todos:', store.getState())
})
// Dispatch экшенов
store.dispatch({ type: 'ADD_TODO', payload: 'Изучить Redux' })
store.dispatch({ type: 'ADD_TODO', payload: 'Практика Redux Toolkit' })
const todos = store.getState()
store.dispatch({ type: 'TOGGLE_TODO', payload: todos[0].id })
console.log('Финальное состояние:', store.getState())Создай простой Redux store для управления корзиной покупок. Реализуй редьюсер с экшенами ADD_ITEM, REMOVE_ITEM, CLEAR_CART. Каждый товар имеет id, name, price, quantity.
ADD_ITEM: item.quantity + 1. REMOVE_ITEM: filter(item => item.quantity > 0). CLEAR_CART: return [].