Slide 1

Slide 1 text

Win-win с react.js Максим Климишин ! CTO at Zakaz.ua ! ! @maxmaxmaxmax

Slide 2

Slide 2 text

• Бегаю • Рублю дрова • Увлекаюсь политикой Обо мне

Slide 3

Slide 3 text

React.js

Slide 4

Slide 4 text

React.js JavaScript библиотека для создания UI (Wikipedia) ! ! Надо описать, как приложение должно выглядеть в любой момент времени и React.js автоматически будет управлять всеми обновлениями UI, если основные данные поменяются

Slide 5

Slide 5 text

Что такое UI? UI – это интерактивная проекция состояния приложения

Slide 6

Slide 6 text

React.js tree • Компоненты React.js реализованы в виде дерева • Есть Root Node, от которой все пляшет • Каждый компонент может содержать дочерние компоненты • В дочерние компоненты можно передавать состояние в виде аттрибутов • Дочерний компонент не может изменить props, которые были ему переданы из родительского компонента

Slide 7

Slide 7 text

Виртуальное DOM дерево • Virtual DOM - это объекты JS, которые описывают структуру UI • Реакт использует алгоритм, для нахождения минимального числа шагов модификаций DOM дерева в браузере

Slide 8

Slide 8 text

JSX • XML-похожий трансформер синтаксиса в JavaScript (React.DOM) ! • Визуализирует структуру DOM внутри React.js компонент ! • Помогает избежать избыточного кода на чистом JavaScript и повысить читаемость компонент

Slide 9

Slide 9 text

Hello, John! /** @jsx React.DOM */! var HelloMessage = React.createClass({! render: function() {! return
Hello {this.props.name}
;! }! });! ! React.renderComponent(! , mountNode);!

Slide 10

Slide 10 text

JSX to JS /** @jsx React.DOM */! var HelloMessage = React.createClass({displayName: 'HelloMessage',! render: function() {! return React.DOM.div(null, "Hello ", this.props.name);! }! });! ! React.renderComponent(! HelloMessage( {name:"John"} ), document.getElementById("hello"));!

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Rendering • Во время вызова setState реакт помечает его как “грязный” (dirty) и перестраивает виртуальное DOM дерево • На следующей итерации event loop-a происходит обновление

Slide 13

Slide 13 text

Diff алгоритмы и массивы • Особый случай для списков - по умолчанию элементы списка ассоциировались последовательно • Для однозначного маппинга между элементом списка и компонентой React.js необходимо указывать ключ

Slide 14

Slide 14 text

Решаем сами, что рендерим • По желанию можно самостоятельно решать изменилось ли дерево boolean shouldComponentUpdate( object nextProps, object nextState)

Slide 15

Slide 15 text

Синтетические события • React.js слушает события только с корневой ноды • Когда событие происходит, react.js ищет компонент, соответствующей ноде, которая сгенерировала событие • Дальше React.js оборачивает событие в SyntheticEvent • И это дело работает совершенно одинаково во всех поддерживаемых браузерах

Slide 16

Slide 16 text

Работа с CSS • Поначалу в React.js было неудобно работать с классами CSS
• Но появился classSet и жизнь наладилась

Slide 17

Slide 17 text

classSet { render: function() { var cx = React.addons.classSet; var classes = cx({ 'message': true, 'message-important': this.props.isImportant, 'message-read': this.props.isRead }); // same final string, but much cleaner return (
Great, I\'ll be there.
) } }

Slide 18

Slide 18 text

Рутинное телодвижение кажется сложным var NoLink = React.createClass({ getInitialState: function() { return {value: 'Hello!'}; }, handleChange: function(event) { this.setState({value: event.target.value}); }, render: function() { var value = this.state.value; return ; } });

Slide 19

Slide 19 text

Two way data binding • Angular и Ember разбаловал некоторых разработчиков в плане two-way data binding. ! • Но пацанчики из facebook оказались ровными и сделали linkState …

Slide 20

Slide 20 text

Two way data binding var WithLink = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return {value: 'Hello!'}; }, render: function() { return ; } });

Slide 21

Slide 21 text

Чем хорошо для дела • Практически нет гемора для поддержки зоопарка браузеров • Быстрая и “не распухающая” разработка новых фич • Легко внедряется в существующий и работающий код • Легко ре-использовать компоненты • Сложно написать “говнокод” - помогает односторонний data flow

Slide 22

Slide 22 text

Производительность Based on: http://vuejs.org/perf/ Backbone React Plain JS 0 10 20 30 40 Анимация 100 кружков, Chrome 34, ~ms на цикл

Slide 23

Slide 23 text

Model & Controller React.js занимается только уровнем представления

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

А что насчет приложений?

Slide 26

Slide 26 text

Flux

Slide 27

Slide 27 text

Flux - это архитектура/design pattern приложений для Rect.js, которая использует однонаправленный поток данных

Slide 28

Slide 28 text

Идея архитектуры Flux

Slide 29

Slide 29 text

Что внутри Flux? • По сути Flux - design pattern, уникальная тулза - Dispatcher • В экземпляр диспетчера региструются колебли, присваивается уникальный ID • Диспетчеру можно послать некоторое событие (dispatcher.dispatch) • Внутри коллбека можно объявить зависимость от выполнения другого (dispatcher.waitFor) • Коллбеки будут выполнены согласно описанным зависимостям

Slide 30

Slide 30 text

Какую проблемы решает Flux? • Мультинаправленное движение данных внутри приложения • Структурную организацию React.js- based приложений • Избыточный инструментарий, которые приезжает с хранилищами из других подходов • Структурирование зависимостей хэндлеров событий

Slide 31

Slide 31 text

Bidirectional data flow Button 1 Button 2 Input 1 Input 2 Result area 1 Result area 2 Handler 3 API Endpoint 1 API Endpoint 2 API Endpoint 3 Handler 2 Handler 1 Handler 4 Среднесложное приложение на jQuery

Slide 32

Slide 32 text

Bidirectional data flow Action View 1 View 2 View 3 State Action State State State

Slide 33

Slide 33 text

Flux Dispatcher var base = new Dispatcher(); var v1 = {"country": null}, v2 = {"city": null}, v3 = {"price": null}; ! v1.dispatchToken = base.register(function (payload) { console.log("v1 handler"); if (payload.actionType == "update-v1") v1.country = payload.country; console.log(v1.country, v2.city, v3.price); }); !

Slide 34

Slide 34 text

Flux Dispatcher v2.dispatchToken = base.register(function (payload) { console.log("v2 handler"); if (payload.actionType === "update-v1") { base.waitFor([v1.dispatchToken]); v2.city = payload.country + " - related data to v2"; } console.log(v1.country, v2.city, v3.price); }); ! base.register(function (payload) { console.log("v3 handler"); if (payload.actionType === "update-v2") { base.waitFor([v1.dispatchToken, v2.dispatchToken]); v2.city = payload.city; v3.price = 123; } console.log(v1.country, v2.city, v3.price); });

Slide 35

Slide 35 text

Flux Dispatcher ! document.getElementById("dispatch").addEventListener("click", function () { base.dispatch({ actionType: "update-v1", country: 'ukraine' }); base.dispatch({ actionType: "update-v2", city: "kiev"}); });

Slide 36

Slide 36 text

Результат v1 handler ukraine kiev 123 v2 handler ukraine ukraine - related data to v2 123 v3 handler ukraine ukraine - related data to v2 123 ! v1 handler ukraine ukraine - related data to v2 123 v2 handler ukraine ukraine - related data to v2 123 v3 handler ukraine kiev 123

Slide 37

Slide 37 text

А нахера это нужно? Разделение ответственности (Separation of concerns) - уменьшать связанность между модулями, увеличивать связность внутри модуля Please, stop the bullshit © John Legere, T-Mobile CEO

Slide 38

Slide 38 text

Coupling vs cohesion? • Связанность плоха тем, что она мешает менять компоненты независимо от общего кода • Разработчику необходимо понимать как работает вся система для того, чтобы безопасно внести изменения • Изменения требований потенциально влечет рефакторинг нескольких компонент • Стоимость изменений выше

Slide 39

Slide 39 text

Спасибо за горячую воду, Львов!

Slide 40

Slide 40 text

Спасибо! ! facebook.github.io/react/ ! facebook.github.io/flux/