Reflux

Последнее обновление: 09.10.2018

Reflux представляет собой решение, суть которого упростить создание архитектуры приложения на React по сравнению с использованием Flux. В каком-то роде Reflux может рассматриваться как замена Flux, которая упрощает взаимодействие между различными частями приложения.

Основу Reflux составляют три компонента:

  • Действие (action) содержит определения всех применяемых действий в приложении

  • Компонент представления (view component) - собственно визуальная часть приложения, в роли которого обычно используется объект Reflux.Component. Класс Reflux.Component является расширением стандартного класса React.Component

  • Хранилище (store) хранит данные и логику приложения

В целом мы получаем ту же самую архитектуру, что и во Flux, только без диспетчера:

Reflux и React

В этой схеме с помощью действий компонент представлений направляет в хранилище команду. Получив команду, хранилище изменяет свое состояние, что приводит к обновлению компонента представлений.

Рассмотрим на примере. Создадим новый проект. Для этого определим каталог refluxapp. Сначала добавим в проект новый файл package.json:

{
    "name": "refluxapp",
    "description": "A React.js project using Reflux",
    "version": "1.0.0",
    "author": "metanit.com",
    "scripts": {
      "dev": "webpack-dev-server --hot --open",
      "build": "webpack"
    },
    "dependencies": {
      "react": "^16.5.0",
      "react-dom": "^16.5.0",
      "reflux": "^6.4.1"
    },
    "devDependencies": {
        "@babel/core": "^7.1.2",
		"babel-loader": "^8.0.0",
		"@babel/preset-env": "^7.1.0",
		"@babel/preset-react":"^7.0.0",
		"webpack": "^4.20.0",
		"webpack-cli": "^3.1.2",
		"webpack-dev-server": "^3.1.9"
    }
}

Чтобы использовать Reflux, здесь определяется зависимость "reflux". Кроме того, поскольку данный проект будет разделен на модули, то для их компиляции и сборки будут использоваться пакеты babel и webpack.

Также добавим в каталог проекта главную страницу приложения index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Reflux в React</title>
</head>
<body>
    <div id="container"></div>
    <script src="public/bundle.js"></script>
</body>
</html>

Для файлов приложения определим в проекте новую папку app. Итак, наше приложение будет очень простым: оно будет выводить список объектов с возможностью добавления и удаления данных.

Вначале добавим определение действий. Для этого определим в папке app новый файл actions.jsx со следующим содержимым:

var Reflux = require("reflux");
var Actions = Reflux.createActions(["addItem", "removeItem"]);
module.exports = Actions;

Итак, здесь подключаем функциональность Reflux и с помощью метода Reflux.createActions() создаем набор действий. В нашем случае это будут действия добавления и удаления элемента списка.

Далее определим хранилище. Для этого добавим в папку app новый файл phonestore.jsx:

var Reflux = require("reflux");
var Actions = require("./actions.jsx");

class PhonesStore extends Reflux.Store {
	constructor()
    {
        super();
		this.state = {phones: ["iPhone 7", "Samsung Galaxy S8"]};
		
        this.listenTo(Actions.addItem, this.onAddItem);
        this.listenTo(Actions.removeItem, this.onRemoveItem);
    }
	
	onAddItem(phone){
		
		this.state.phones.push(phone);
	}
	onRemoveItem(phone){
		
		var data = this.state.phones;
		var index = data.indexOf(phone);
		if (index > -1) {
			data.splice(index, 1);
			this.setState({phones: data});
		}
	}
}

module.exports = PhonesStore;

Хранилище наследуется от класса Reflux.Store. В нем также, как и в стандартных компонентах React, мы можем определить состояние state. В данном случае в хранилище определен массив phones - тот список, который будет выводиться на веб-страницу.

Кроме того, в конструкторе хранилища связываем действия с методами хранилища:

this.listenTo(Actions.addItem, this.onAddItem);
this.listenTo(Actions.removeItem, this.onRemoveItem);

То есть тем самым мы указываем, какой метод будет вызываться при получении хранилищем той или иной команды. Так, при получении команды Actions.addItem будет вызываться метод onAddItem(), который будет добавлять новый элемент в массив.

При получении команды Actions.removeItem будет происходить удаление указанного элемента из массива.

Теперь добавим в папку app новый файл phoneslist.jsx, который будет содержать визуальные компоненты:

var React = require("react");
var Reflux = require("reflux");
var Actions = require("./actions.jsx");
var PhonesStore = require("./phonestore.jsx");

class PhonesList extends Reflux.Component{

    constructor(props){
		super(props);
		this.state = {newItem: ""};
		this.store = PhonesStore;
		
		this.onInputChange = this.onInputChange.bind(this);
		this.onClick = this.onClick.bind(this);
	}
	onInputChange(e){
		this.setState({newItem:e.target.value});
	}
	onClick(e){
		if(this.state.newItem){
			Actions.addItem(this.state.newItem);
			this.setState({newItem:" "});
		}
	}
	onRemove(item){
		if(item){
			Actions.removeItem(item);
		}
	}
	render(){
		
		var remove = this.onRemove;
		return <div> 
				<input type="text" value={this.state.newItem} onChange={this.onInputChange} />	
				<button onClick={this.onClick}>Добавить</button>				
                <h2>Список смартфонов</h2>
                <div>
                    {
                        this.state.phones.map(function(item){
							
                            return <Phone key={item} text={item} onRemove={remove} />
                        })
                    }
                </div>
            </div>;
    }
}

class Phone extends React.Component{

    constructor(props){
		super(props);
		this.state = {text: props.text};
		this.onClick = this.onClick.bind(this);
	}
	onClick(e){
		this.props.onRemove(this.state.text);
	}
	render(){
		return <div> 
				<p>
					<b>{this.state.text}</b><br />
					<button onClick={this.onClick}>Удалить</button>	
				</p>
            </div>;
    }
}

module.exports = PhonesList;

Главным компонентом является PhonesList. Он наследуется от класса Reflux.Component. Reflux.Component расширяет стандартный класс React.Component, поэтому здесь мы можем работать как со стандартным компонентом. Однако необязательно наследовать все компоненты от Reflux.Component.

В конструкторе компонента с помощью свойства this.store определяется хранилище, с которым связан компонент. Если вдруг у нас несколько хранилищ, то мы могли бы определить другое свойство - this.stores, которое принимает массив хранилищ.

Для отслеживания добавляемого элемента в состоянии компонента определяется объект this.state.newItem.

При нажатии на кнопку на форме добавления срабатывает обработчик onClick(), в котором вызывается действие Actions.addItem. А при выполнении метода onRemove() будет вызываться действие Actions.removeItem. Таким образом, посредством действий из компонента мы можем направлять команду хранилищу.

И также в папке app определим файл app.jsx, который будет содержать логику установки компонента на веб-страницу:

var ReactDOM = require("react-dom");
var React = require("react");
var PhonesList = require("./phoneslist.jsx");
 
ReactDOM.render(
    <PhonesList />,
    document.getElementById("container")
)

И в конце, так как мы будем использовать Webpack, добавим в корневой каталог проекта файл webpack.config.js:

var path = require('path');
 
module.exports = {
   entry: "./app/app.jsx", // входная точка - исходный файл
   output:{
       path: path.resolve(__dirname, './public'),     // путь к каталогу выходных файлов - папка public
       publicPath: '/public/',
       filename: "bundle.js"       // название создаваемого файла
   },
   module:{
       rules:[   //загрузчик для jsx
           {
               test: /\.jsx?$/, // определяем тип файлов
               exclude: /(node_modules)/,  // исключаем из обработки папку node_modules
               loader: "babel-loader",   // определяем загрузчик
               options:{
                   presets:["@babel/preset-env", "@babel/preset-react"]    // используемые плагины
               }
           }
       ]
   }
}

В итоге весь проект будет выглядеть следующим образом:

Сборка Webpack в Reflux и React

Перейдем в терминале/командной строке к местоположению проекта и для установки пакетов выполним команду:

npm install

Затем для компиляции и упаковки файлов вызовем команду:

npm run build

Эта команда сгенерирует файл public/bundle.js, который будет подключаться на веб-страницу.

И в конце запустим проект на выполнение командой npm run dev:

Архитектура Reflux в React
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850