Разбираемся со связкой React и Redux на простейшем примере

14.06.2018 / oberset

Простой пример, который поможет быстро разобраться, как управлять данными с помощью библиотеки Redux в ваших приложениях на React.

Настройка проекта

Первое, что нам необходимо сделать перед запуском приложения на React – это настроить сборщик Webpack и трансформатор javascript-кода Babel. Вначале установим нужные npm-пакеты:

Скачиваем Webpack: npm install -g webpack webpack-cli Скачиваем Babel и необходимые плагины: npm install --save-dev babel-core babel-loader babel-polyfill babel-preset-es2015 babel-preset-react babel-plugin-transform-decorators-legacy babel-plugin-transform-class-properties Скачиваем React и Redux: npm install --save react react-dom prop-types redux react-redux После установки npm-пакетов, в корневой папке проекта нужно создать конфигурационные файлы webpack.config.js и .babelrc.

Содержимое файла webpack.config.js: 'use strict'; var path = require("path"); module.exports = { mode: 'development', entry: { "index": "./index.js" }, output: { path: path.join(__dirname, "build"), filename: "[name].bundle.js" }, module: { rules: [ { test: /\.js$/, use: "babel-loader" } ] }, devtool: "source-map", watch: true, watchOptions: { aggregateTimeout: 300 } };

Содержимое файла .babelrc: { "presets": ["react", "es2015"], "plugins": [ "transform-decorators-legacy", "transform-class-properties" ] } Теперь создадим в корневой папке проекта файлы index.js и index.html.

Файл index.js: console.log('Start React Application!!!') Файл index.html: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Test react-redux</title> </head> <body> <div id="test-app"></div> <script src="build/index.bundle.js"></script> </body> </html> Запускаем webpack из корневой папки: webpack-cli После запуска webpack должен создать js-файл index.bundle.js и положить его в папку build (как мы указали в конфиге). Если все прошло успешно, то в консоли отобразится примерно такое содержимое:

  • Результат запуска webpack-cli в консоли

    Запуск webpack-cli в консоли

Попробуем открыть файл index.html в браузере:

  • Все готово для старта

    Все готово для старта

После настройки проекта можно переходить непосредственно к разработке нашего приложения с использованием React и Redux.

Взаимодействие React и Redux на примере отображения значения счетчика

Для демонстрации примера работы библиотеки Redux в связке с React, создадим небольшое приложение, которое будет отображать в браузере значение счетчика. Так как кода в нашем проекте будет совсем немного, для наглядности примера мы не будем разбивать приложение на множество файлов (хотя в реальном проекте это будет обязательно), а объединим весь код в файле index.js. Откроем файл index.js, созданный нами ранее и вместо вывода сообщения в консоль, подключим следующие пакеты: import React from 'react'; import ReactDOM from 'react-dom'; import {createStore, combineReducers} from 'redux'; import {Provider, connect} from 'react-redux'; import PropTypes from 'prop-types'; Тут мы импортировали сам фреймворк "реакт", пакет react-dom для отображения реакт-компонентов в структуре DOM браузера, функции библиотеки Redux и пакет "react-redux", который и осуществляет взаимодействие "реакта" и "редукса".

Добавим код для установки значения счетчика: let counter = 1; const counterReducer = (state = null, action) => { switch (action.type) { case 'TEST': return action.counter; default: return state; } }; const store = createStore( combineReducers({counter: counterReducer}), {counter} ); Redux хранит все данные приложения в едином хранилище (store), который создается с помощью функции createStore. В нашем примере store хранит только одно поле counter. Для обновления значения в store нужно создать функцию, которая принимает в качестве параметров текущее значение state и действие action. Действие – это обычный javascript-объект, состоящий из типа действия (обязательного поля type) и произвольных полей, из которых потом можно вернуть новое значение для store. В нашем случае функция counterReducer возвращает новое значение счетчика из поля action.counter. В функции также производится проверка action.type, чтобы обрабатывать только указанный тип действий.

В качестве второго параметра в функцию createStore можно передать исходное состояние хранилища, мы таким образом можем установить начальное значение счетчика из переменной counter.

Подпишемся на обновление хранилища, чтобы выводить в консоль текущее состояние: store.subscribe(() => console.log(store.getState())); Далее создадим React-компонент для отображения счетчика: @connect( state => ({ counter: state.counter }), dispatch => ({}) ) class App extends React.Component { static contextTypes = { store: PropTypes.object }; render() { return ( <h1>Counter value: {this.props.counter}</h1> ); } } Декоратор @connect, добавленный к компоненту, производит привязку значения из хранилища store к свойству компонента. Т.е значение поля counter из store теперь можно прочитать из this.props.

Далее нам остается отобразить компонент в браузере используя метод render из пакета "react-dom" и добавить тестовую функцию для обновления значения счетчика: ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('test-app') ); setInterval(() => { store.dispatch({ type: 'TEST', counter: ++counter }); }, 1000); Компонент Provider из пакета "react-redux" добавляет store ко всем вложенным компонентам. Метод store.dispatch запускает механизм обновления хранилища, в качестве параметра он принимает объект действия, состоящий из типа действия и нового значения счетчика.

После запуска примера в браузере, можно увидеть, как значение счетчика каждую секунду увеличивается на 1. Каждое обновление состояния хранилища выводится в консоль.

  • Вывод счетчика в браузере

Полный код приложения: import React from 'react'; import ReactDOM from 'react-dom'; import {createStore, combineReducers} from 'redux'; import {Provider, connect} from 'react-redux'; import PropTypes from 'prop-types'; let counter = 1; const counterReducer = (state = null, action) => { switch (action.type) { case 'TEST': return action.counter; default: return state; } }; const store = createStore( combineReducers({counter: counterReducer}), {counter} ); store.subscribe(() => console.log(store.getState())); @connect( state => ({ counter: state.counter }), dispatch => ({}) ) class App extends React.Component { static contextTypes = { store: PropTypes.object }; render() { return ( <h1>Counter value: {this.props.counter}</h1> ); } } ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('test-app') ); setInterval(() => { store.dispatch({ type: 'TEST', counter: ++counter }); }, 1000);

Надеюсь, этот простейший пример поможет вам разобраться с использованием связки React и Redux.

Обзоры по теме:
Комментарии (0)

Зарегистрируйтесь или авторизуйтесь, чтобы оставлять комментарии.