Skip to main content

Быстрый старт с React Redux

Чему вы научитесь?
  • Установке и использованию Redux Toolkit вместе с React 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) и экспортируем его:

app/store.js
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):

index.js
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, что позволяет писать "мутабельную" логику обновления состояния, которая становится корректным иммутабельным вариантом.

features/counter/counterSlice.js
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) из среза для обработки изменений этого состояния.

app/store.js
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>.

features/counter/Counter.js
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, и вызовите её с определённым действием для изменения состояния

Полный пример приложения со счётчиком

Пример приложения счётчика также представлен здесь

Вот полное приложение счетчика в виде запущенной CodeSandbox:

Что дальше?

Мы рекомендуем пройти руководства "Redux Essentials" и "Redux Fundamentals" из документации самого Redux. Они дадут вам полное понимание работы Redux, что назначение Redux Toolkit и React Redux, а также способ их корректного использования.