Быстрый старт с React Redux
Чему вы научитесь?
- Установке и использованию Redux Toolkit вместе с React Redux
Предварительные требования
- Знакомство с синтаксисом ES6 и его возможностями
- Знания о терминологии React: JSX, состояние, функциональные компоненты, пропсы и хуки
- Понимание терминов и концепции Redux
Введение
Добро пожаловать в начальное руководство по React Redux! Это руководство вкратце представит вам React Redux и обучит использовать его корректно.
Как читать это руководство?
Эта страница будет акцентировать внимание только на первичную установку приложения с Redux и Redux Toolkit, а также познакомит с главными API, которые вы будете использовать. Для понимания работы Redux и изучения полных примеров использования Redux Toolkit, посмотрите руководства в документации самого Redux.
В этом руководстве мы предположим, что вы используете Redux Toolkit и React Redux вместе, в качестве стандартного шаблона использования Redux. В примерах используется типичная структура папок, созданная Create-React-App, где весь код приложения хранится в папке src
. Как бы то ни было, описанные паттерны могут быть адаптированы для любого проекта и файловой структуры, которую вы используете.
Redux+JS шаблон для Create-React-App устанавливает уже настроенный проект.
Резюме
Установите Redux Toolkit и React Redux
Добавьте пакеты Redux Toolkit и React Redux в ваш проект:
npm install @reduxjs/toolkit react-redux
Создайте Redux хранилище(store)
Добавьте файл src/app/store.js
. Импортируйте configureStore
API из Redux Toolkit. Сначала мы создадим пустое Redux хранилище(store) и экспортируем его:
import { configureStore } from '@reduxjs/toolkit'
export default configureStore({
reducer: {},
})
Это создаст Redux хранилище(store) и автоматически настроит Redux DevTools расширение, таким образом вы сможете просматривать содержимое хранилища(store) во время разработки.
Обозначим Redux хранилище(store) в React
Единожды создаётся Redux хранилище(store), которое мы делаем доступным во всех React компонентах, обернув приложение в React Redux <Provider>
в файле src/index.js
. Импортируйте созданное на предыдущем шаге Redux хранилище(store) и оберните ваше приложение <App>
в <Provider>
, которому необходимо предоставить в пропс store
наше Redux хранилище(store):
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import store from './app/store'
import { Provider } from 'react-redux'
// React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<Provider store={store}>
<App />
</Provider>
)
Создайте "срез" (часть хранилища/slice) Redux хранилища(store)
Добавьте новый файл src/features/counter/counterSlice.js
. В этом файле импортируйте createSlice
API из Redux Toolkit.
Создание среза Redux хранилища(store) требует строковое имя, с которым будет ассоциирован этот срез, изначальное состояние и 1 или больше функций редюсеров(reducer) для определения, как состояние может быть изменено. После создания среза мы можем экспортировать сгенерированные действия(action creators) и функции редюсеры(reducer) для этого среза.
Redux требует, чтобы все обновления состояния были иммутабельны, это достигается путём копирования данных и обновления этих копий. Как бы то ни было, createSlice
и createReducer
от Redux Toolkit используют библиотеку Immer, что позволяет писать "мутабельную" логику обновления состояния, которая становится корректным иммутабельным вариантом.
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
// Redux Toolkit позволяет нам писать "мутабельную" логику в reducer'ах.
// Это не изменяет состояние(state) напрямую, потому что внутри используется библиотека Immer,
// которая следит за изменениями в "черновом state" и создает новое
// неизменное состояние на основе этих изменений
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})
// Функция действия генерируется на каждую функцию релюсера(reducer), определённую в createSlice
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
Добавляем редюсер(reducer) функции созданного среза в Redux хранилище(store) приложения
Далее, нам нужно импортировать функцию редюсера(reducer) из среза для счётчика и добавить их в наше хранилище(store). Определением поля в параметре reducers
мы говорим хранилищу(store) использовать функцию редюсера(reducer) из среза для обработки изменений этого состояния.
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer,
},
})
Использование состояния из Redux хранилища(store) и действий в компонентах React
Теперь мы можем использовать хуки из React Redux, чтобы позволить React компонентам взаимодействовать с Redux хранилищем(store). Мы можем читать состояние из хранилища(store) при помощи хука useSelector
и вызывать действия, используя useDispatch
. Создайте файл src/features/counter/Counter.js
с компонентом <Counter>
, затем импортируйте этот компонент в App.js
и поставьте его внутрь <App>
.
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
import styles from './Counter.module.css'
export function Counter() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Увеличить значение"
onClick={() => dispatch(increment())}
>
Увеличить
</button>
<span>{count}</span>
<button
aria-label="Уменьшить значение"
onClick={() => dispatch(decrement())}
>
Уменьшить
</button>
</div>
</div>
)
}
Теперь в любое время вы можете нажать на кнопки "Увеличить" и "Уменьшить":
- Соответствующее Redux действие будет отправляться в хранилище(store)
- Reducer среза счётчика будет видеть действия и обновлять нужную часть состояния
- Компонент
<Counter>
будет получать новое состояние из хранилища(store) и перерисовываться с новыми данными -->
Чему вы научились
Это был краткий осмотр того, как установить и использовать Redux Toolkit с React. Подводя итоги:
Резюме
- Создайте Redux хранилище(store) с
configureStore
configureStore
принимает функцииreducer
как именнованный аргументconfigureStore
автоматически устанавливает хранилище(store) со значениями по умолчанию
- Предоставьте Redux хранилище(store) компонентам React приложения
- Оберните ваш
<App />
в компонент<Provider>
из React Redux - Передайте Redux хранилище(store)
<Provider store={store}>
- Оберните ваш
- Создайте функцию reducer для Redux "среза" ("slice") при помощи
createSlice
- Вызовите
createSlice
со строковым именем среза, начальное значение и поимённо функции редюсеров (reducer) - Функции редюсеров(Reducer) могут "мутировать" состояние, т.к. внутри использует библиотека Immer
- Экспортируйте созданный редюсер(reducer) среза и его действия
- Вызовите
- Используйте хуки
useSelector/useDispatch
из React Redux в React компонентах- Читайте данные из хранилища(store) с помощью хука
useSelector
- Получите функцию
dispatch
с хукомuseDispatch
, и вызовите её с определённым действием для изменения состояния
- Читайте данные из хранилища(store) с помощью хука
Полный пример приложения со счётчиком
Пример приложения счётчика также представлен здесь
Вот полное приложение счетчика в виде запущенной CodeSandbox:
Что дальше?
Мы рекомендуем пройти руководства "Redux Essentials" и "Redux Fundamentals" из документации самого Redux. Они дадут вам полное понимание работы Redux, что назначение Redux Toolkit и React Redux, а также способ их корректного использования.