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

LvivJS 2014 - Win-win c React.js

Embed Size (px)

Citation preview

Page 1: LvivJS 2014 - Win-win c React.js

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

Page 2: LvivJS 2014 - Win-win c React.js

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

Обо мне

Page 3: LvivJS 2014 - Win-win c React.js

React.js

Page 4: LvivJS 2014 - Win-win c React.js

React.js

JavaScript библиотека для создания UI (Wikipedia)

!

!

Надо описать, как приложение должно выглядеть в любой момент времени и

React.js автоматически будет управлять всеми обновлениями UI, если основные

данные поменяются

Page 5: LvivJS 2014 - Win-win c React.js

Что такое UI?

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

Page 6: LvivJS 2014 - Win-win c React.js

React.js tree

• Компоненты React.js реализованы в виде дерева

• Есть Root Node, от которой все пляшет • Каждый компонент может содержать дочерние компоненты

• В дочерние компоненты можно передавать состояние в виде аттрибутов

• Дочерний компонент не может изменить props, которые были ему переданы из родительского компонента

Page 7: LvivJS 2014 - Win-win c React.js

Виртуальное DOM дерево• Virtual DOM - это объекты JS, которые описывают структуру UI

• Реакт использует алгоритм, для нахождения минимального числа шагов модификаций DOM дерева в браузере

Page 8: LvivJS 2014 - Win-win c React.js

JSX

• XML-похожий трансформер синтаксиса в JavaScript (React.DOM) !

• Визуализирует структуру DOM внутри React.js компонент !

• Помогает избежать избыточного кода на чистом JavaScript и повысить читаемость компонент

Page 9: LvivJS 2014 - Win-win c React.js

Hello, John!

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

Page 10: LvivJS 2014 - Win-win c React.js

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"));!

Page 11: LvivJS 2014 - Win-win c React.js
Page 12: LvivJS 2014 - Win-win c React.js

Rendering• Во время вызова setState реакт помечает его как “грязный” (dirty) и перестраивает виртуальное DOM дерево

• На следующей итерации event loop-a происходит обновление

Page 13: LvivJS 2014 - Win-win c React.js

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

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

Page 14: LvivJS 2014 - Win-win c React.js

Решаем сами, что рендерим• По желанию можно самостоятельно решать изменилось ли дерево

boolean shouldComponentUpdate( object nextProps, object nextState)

Page 15: LvivJS 2014 - Win-win c React.js

Синтетические события• React.js слушает события только с корневой ноды

• Когда событие происходит, react.js ищет компонент, соответствующей ноде, которая сгенерировала событие

• Дальше React.js оборачивает событие в SyntheticEvent

• И это дело работает совершенно одинаково во всех поддерживаемых браузерах

Page 16: LvivJS 2014 - Win-win c React.js

Работа с CSS

• Поначалу в React.js было неудобно работать с классами CSS

<div className=“class-a class-b class-c class-d class-e class-f class-…> </div>

• Но появился classSet и жизнь наладилась

Page 17: LvivJS 2014 - Win-win c React.js

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 ( <div className={classes}>Great, I\'ll be there.</div> ) } }

Page 18: LvivJS 2014 - Win-win c React.js

Рутинное телодвижение кажется сложным

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 <input type="text" value={value} onChange={this.handleChange} />; } });

Page 19: LvivJS 2014 - Win-win c React.js

Two way data binding

• Angular и Ember разбаловал некоторых разработчиков в плане two-way data binding.

!

• Но пацанчики из facebook оказались ровными и сделали linkState …

Page 20: LvivJS 2014 - Win-win c React.js

Two way data binding

var WithLink = React.createClass({ mixins: [React.addons.LinkedStateMixin], getInitialState: function() { return {value: 'Hello!'}; }, render: function() { return <input type="text" valueLink={this.linkState('value')} />; } });

Page 21: LvivJS 2014 - Win-win c React.js

Чем хорошо для дела• Практически нет гемора для поддержки зоопарка браузеров

• Быстрая и “не распухающая” разработка новых фич

• Легко внедряется в существующий и работающий код

• Легко ре-использовать компоненты • Сложно написать “говнокод” - помогает односторонний data flow

Page 22: LvivJS 2014 - Win-win c React.js

Производительность

Based on: http://vuejs.org/perf/

Backbone

React

Plain JS

0 10 20 30 40

Анимация 100 кружков, Chrome 34, ~ms на цикл

Page 23: LvivJS 2014 - Win-win c React.js

Model & Controller

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

Page 24: LvivJS 2014 - Win-win c React.js
Page 25: LvivJS 2014 - Win-win c React.js

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

Page 26: LvivJS 2014 - Win-win c React.js

Flux

Page 27: LvivJS 2014 - Win-win c React.js

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

использует однонаправленный поток данных

Page 28: LvivJS 2014 - Win-win c React.js

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

Page 29: LvivJS 2014 - Win-win c React.js

Что внутри Flux?

• По сути Flux - design pattern, уникальная тулза - Dispatcher

• В экземпляр диспетчера региструются колебли, присваивается уникальный ID

• Диспетчеру можно послать некоторое событие (dispatcher.dispatch)

• Внутри коллбека можно объявить зависимость от выполнения другого (dispatcher.waitFor)

• Коллбеки будут выполнены согласно описанным зависимостям

Page 30: LvivJS 2014 - Win-win c React.js

Какую проблемы решает Flux?

• Мультинаправленное движение данных внутри приложения

• Структурную организацию React.js-based приложений

• Избыточный инструментарий, которые приезжает с хранилищами из других подходов

• Структурирование зависимостей хэндлеров событий

Page 31: LvivJS 2014 - Win-win c React.js

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

Page 32: LvivJS 2014 - Win-win c React.js

Bidirectional data flow

Action

View 1

View 2

View 3

State Action

State

State

State

Page 33: LvivJS 2014 - Win-win c React.js

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); }); !

Page 34: LvivJS 2014 - Win-win c React.js

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); });

Page 35: LvivJS 2014 - Win-win c React.js

Flux Dispatcher

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

Page 36: LvivJS 2014 - Win-win c React.js

Результат

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

Page 37: LvivJS 2014 - Win-win c React.js

А нахера это нужно?

Разделение ответственности (Separation of concerns) - уменьшать связанность между модулями, увеличивать связность внутри модуля

Please, stop the bullshit © John Legere, T-Mobile CEO

Page 38: LvivJS 2014 - Win-win c React.js

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

• Разработчику необходимо понимать как работает вся система для того, чтобы безопасно внести изменения

• Изменения требований потенциально влечет рефакторинг нескольких компонент

• Стоимость изменений выше

Page 39: LvivJS 2014 - Win-win c React.js

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

Page 40: LvivJS 2014 - Win-win c React.js

Спасибо!

!

facebook.github.io/react/!

facebook.github.io/flux/