Прежде чем продолжить этот блог, я бы рекомендовал сначала ознакомиться с первой частью серии статей “Понимание Redux”, которую можно найти по этой ссылке “Понимание Redux (часть 1): Демистификация Store, Action и Reducers. Это поможет вам понять текущую статью. В блоге части 1 я попытался объяснить фундаментальные принципы/концепции Redux. Я рассказал о том, что такое Store, Actions и Reducers, что делает Redux предсказуемым, а также привел пример.
В этой статье мы попробуем создать собственное приложение на базе Redux. Мы рассмотрим, как создать Store и предоставить его приложению, написать Actions, отправлять их при взаимодействии с пользователем, сделать Reducers и обновить хранилище, прочитать хранилище из других компонентов, которые являются дочерними для App, и многое другое. Я буду предоставлять все важные фрагменты кода по ходу дела, чтобы вы могли быстро раскрутить приложение.
Чтобы дать представление о самом начале, вот что мы в итоге создадим
Мы создадим базовое приложение, в котором мы сможем добавлять и удалять товары в корзину. Мы будем управлять изменениями состояния в магазине redux и отображать информацию в пользовательском интерфейсе.
- Настройка кода
- 1. Создайте react-приложение с помощью команды create-react-app
- 2. Перейдите в только что созданную папку с помощью команды
- 3. Установите redux и библиотеку react-redux с помощью команд
- 4. Запустите приложение, используя
- 5. Создание редуктора
- 6. Создание магазина и предоставление его приложению
- 7. Создать действия
- 8. Создание представления/ пользовательского интерфейса
- 9. Чтение/доступ к магазину с помощью хука useSelector
- 10. Диспетчеризация действия при нажатии на кнопку (наряду с обработкой некоторого поведения пользовательского интерфейса в зависимости от состояния) с помощью хука useDispatch.
- Ссылка на Github
- Резюме
- Подведение итогов
- Социальные ссылки
Настройка кода
1. Создайте react-приложение с помощью команды create-react-app
npx create-react-app react-app-with-redux
2. Перейдите в только что созданную папку с помощью команды
cd react-app-with-redux
3. Установите redux и библиотеку react-redux с помощью команд
npm install redux react-redux
4. Запустите приложение, используя
npm start
5. Создание редуктора
Сначала создайте папку внутри src
с именем actionTypes
и создайте в ней файл actionTypes.js
. Этот файл будет содержать все действия, с которыми будет иметь дело приложение. Добавьте следующие строки в actionTypes.js
export const ADD_ITEM = "ADD_ITEM";
export const DELETE_ITEM = "DELETE_ITEM";
Поскольку мы создаем приложение, в котором будет возможность добавлять и удалять элементы, следовательно, два вышеуказанных типа действий.
Далее создайте папку внутри src
под названием reducers
и создайте в ней новый файл с именем cartReducer.js
. Этот файл будет содержать всю логику редуктора, связанную с компонентом корзины. (Примечание: Мы создадим представление/ пользовательский интерфейс на шаге 8). Добавьте следующие строки в cartReducer.js
.
import { ADD_ITEM, DELETE_ITEM } from "../actionTypes/actionTypes";
const initialState = {
numOfItems: 0,
};
export default const cartReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_ITEM:
return {
...state,
numOfItems: state.numOfItems + 1,
};
case DELETE_ITEM:
return {
...state,
numOfItems: state.numOfItems - 1,
};
default:
return state;
}
};
Как мы уже говорили в первой части этого блога, мы создали начальное состояние для приложения и присвоили его параметру по умолчанию state
в функции cartReducer
. Эта функция включает тип отправляемого действия, и в случае совпадения с типом действия вносит необходимые изменения в состояние и возвращает новый экземпляр обновленного состояния. Если ни один из типов действий не совпадает, то состояние возвращается как есть. Наконец, мы делаем экспорт функции cakeReducer
по умолчанию, чтобы использовать ее в процессе создания магазина.
6. Создание магазина и предоставление его приложению
Создайте файл внутри src
с именем store.js
и создайте магазин с помощью команды
const store = createStore()
Добавьте следующие строки в store.js
import { createStore } from "redux";
import { cartReducer } from "./reducers/cartReducer";
const store = createStore(cartReducer);
export default store;
Теперь пришло время предоставить этот store
компоненту App
. Для этого мы используем тег <Provider>
, который мы получаем из библиотеки react-redux
. Мы обернем весь компонент App
внутри тега <Provider>
, используя следующий синтаксис.
// rest of the code ...
<Provider store={store}>
<div>App Component</div>
// child components of App/ other logic
</Provider>
// rest of the code ...
Обернув компонент App
внутри тега <Provider>
, все дочерние компоненты App
получат доступ к store
. Чтобы узнать больше, посетите часть 1 этой серии блогов.
Продолжая работу с файлом App.js
, добавьте в него следующие строки.
import "./App.css";
import { Provider } from "react-redux";
import store from "./store";
function App() {
return (
<Provider store={store}>
<div>App Component</div>
</Provider>
);
}
export default App;
7. Создать действия
Теперь создайте папку внутри src
под названием actions
и создайте в ней файл cartAction.js
. Здесь мы добавим все действия, которые будут выполняться при определенном взаимодействии с пользователем. Добавьте следующие строки в cartAction.js
import { ADD_ITEM, DELETE_ITEM } from "../actionTypes/actionTypes";
const addItem = () => {
return {
type: ADD_ITEM,
};
};
const deleteItem = () => {
return {
type: DELETE_ITEM,
};
};
export { addItem, deleteItem };
В приведенном выше коде мы создали два создателя действий (чистые JS функции, возвращающие объект action
) под названием addItem()
и deleteItem()
. Оба создателя действий возвращают объект action
с определенным type
. Примечание: Каждый объект action
обязательно должен иметь уникальное значение type
. Любые дополнительные данные, передаваемые вместе с объектом действия, являются необязательными и зависят от логики, используемой для обновления state
.
8. Создание представления/ пользовательского интерфейса
Теперь, когда мы создали все необходимые объекты, такие как Store, Actions и Reducers, пришло время создать элементы пользовательского интерфейса. Создайте папку component
внутри src
и создайте в ней файл Cart.js
. Добавьте следующую строку внутри Cart.js
import React from "react";
const Cart = () => {
return (
<div className="cart">
<h2>Number of items in Cart:</h2>
<button className="green">Add Item to Cart</button>
<button className="red">Remove Item from Cart</button>
</div>
);
};
export default Cart;
Добавьте этот компонент Cart
в App.js
.
import "./App.css";
import { Provider } from "react-redux";
import store from "./store";
import Cart from "./component/Cart";
function App() {
return (
<Provider store={store}>
<Cart />
</Provider>
);
}
export default App;
Чтобы сделать его немного презентабельным, я добавил немного базовой стилизации в App.css
следующим образом.
button {
margin: 10px;
font-size: 16px;
letter-spacing: 2px;
font-weight: 400;
color: #fff;
padding: 23px 50px;
text-align: center;
display: inline-block;
text-decoration: none;
border: 0px;
cursor: pointer;
}
.green {
background-color: rgb(6, 172, 0);
}
.red {
background-color: rgb(221, 52, 66);
}
.red:disabled {
background-color: rgb(193, 191, 191);
cursor: not-allowed;
}
.cart {
text-align: center;
}
Вот как выглядит пользовательский интерфейс на данный момент
9. Чтение/доступ к магазину с помощью хука useSelector
useSelector
– это хук, предоставляемый библиотекой react-redux, который помогает нам читать store
и, следовательно, его содержимое (содержимое). Импортируйте хук из react-redux
и используйте следующий синтаксис для чтения магазина с помощью хука useSelector
.
import { useSelector } from "react-redux";
// rest of the code
const state = useSelector((state) => state);
// rest of the code
Таким образом, после добавления хука useSelector
, файл Cart.js
будет выглядеть примерно так
import React from "react";
import { useSelector } from "react-redux";
const Cart = () => {
const state = useSelector((state) => state);
console.log("store", state);
return (
<div className="cart">
<h2>Number of items in Cart:</h2>
<button className="green">Add Item to Cart</button>
<button className="red">Remove Item from Cart</button>
</div>
);
};
export default Cart;
Консольный логгинг состояния даст нам начальное состояние, которое мы задали в файле reducer в шаге 5.
10. Диспетчеризация действия при нажатии на кнопку (наряду с обработкой некоторого поведения пользовательского интерфейса в зависимости от состояния) с помощью хука useDispatch
.
Библиотека react-redux предоставляет нам еще один хук под названием useDispatch
, который помогает нам диспетчеризировать действия или создателей действий, которые в свою очередь возвращают действия. Синтаксис выглядит следующим образом
const dispatch = useDispatch();
dispatch(actionObject or calling the action creator);
Таким образом, добавление диспетчера в наш Cart.js
приведет к тому, что файл будет выглядеть примерно так
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { addItem, deleteItem } from "../actions/cartAction";
const Cart = () => {
const state = useSelector((state) => state);
const dispatch = useDispatch();
return (
<div className="cart">
<h2>Number of items in Cart: {state.numOfItems}</h2>
<button
onClick={() => {
dispatch(addItem());
}}
>
Add Item to Cart
</button>
<button
disabled={state.numOfItems > 0 ? false : true}
onClick={() => {
dispatch(deleteItem());
}}
>
Remove Item to Cart
</button>
</div>
);
};
export default Cart;
Обратите внимание, что при нажатии на кнопку Добавить товар в корзину, мы диспетчеризируем
создателя действия addItem()
, который мы создали в шаге № 7. Аналогично при нажатии на кнопку Remove Item from Cart мы отправляем создателя действия deleteItem()
. Переменная state
хранит состояние приложения, которое по сути является объектом с ключом numOfItems
. Таким образом, state.numOfItems
дает нам текущее значение количества товаров в магазине. Мы отображаем это в представлении в строке <h2>Количество товаров в корзине: {state.numOfItems}</h2>
.
Если копнуть немного глубже, то при нажатии на кнопку Add Item to Cart происходит отправка создателя действия addItem()
, который в свою очередь возвращает объект action
с типом type: ADD_ITEM
. Как упоминалось в первой части этой серии блогов, когда действие отправляется, все редукторы становятся активными. В данном примере у нас только один редуктор, а именно cartReducer
, поэтому он становится активным и слушает диспетчеризацию action
. Как показано на шаге 5, редуктор принимает состояние и действие в качестве входных данных, включает тип action
и возвращает новый экземпляр обновленного состояния. В этом примере, когда действие с типом type: ADD_ITEM
, соответствует первому случаю переключения, оно сначала делает копию всего состояния, используя оператор распространения ...state
, а затем производит необходимое обновление, которое в случае добавления элемента равно numOfItems: state.numOfItems + 1
, то есть увеличивает numOfItems
на 1.
Аналогично, используя ту же логику, при нажатии на кнопку Remove Item from Cart, будет выполнено действие с типом type: DELETE_ITEM
, которое переходит и уменьшает numOfItems
на 1.
Вот демонстрация работающего приложения.
Обратите внимание, как мы смогли управлять поведением кнопки Remove Item from Cart на основе значения numOfItems
в магазине redux. Поскольку отрицательное количество товаров не имеет смысла, мы отключили кнопку удаления товара из корзины, если state.numOfItems <= 0
. Таким образом мы можем ограничить пользователя от уменьшения количества товаров в корзине, если оно уже равно 0. Это был базовый пример, показывающий, как мы можем контролировать поведение различных элементов DOM на основе внутреннего состояния приложения.
Ссылка на Github
Ссылку на Github проекта можно найти здесь: Ссылка на Github
Резюме
В этой статье мы узнали, как быстро раскрутить приложение react на базе redux. Мы узнали, как
- Создавать действия, создателей действий, редукторы и магазин
- Предоставлять магазин приложению с помощью
<Provider>
. - Считывать/получать доступ к хранилищу из компонентов с помощью хука
useSelector
и отображать информацию о состоянии в пользовательском интерфейсе - Диспетчеризация действий на пользовательские события, такие как нажатие кнопки, используя
useDispatch
hook - Управлять поведением DOM-элемента с помощью логики, основанной на состоянии приложения.
Подведение итогов
Спасибо за чтение! Я очень надеюсь, что вам понравилось читать о том, как раскрутить приложение на базе redux react, и вы нашли этот блог полезным. Не забудьте нажать кнопку “Мне нравится” и поделиться с друзьями, я буду вам очень признателен. Оставайтесь с нами, чтобы увидеть еще больше удивительного контента! Мир! 🖖
Социальные ссылки
- Сайт
- Сайт блога