React как беспилотный автомобиль
DataArt (2010-2011)
Stampsy (2012-2015)
?
Даниил Абрамов
Dan Abramov
Stampsy for iPad
Stampsy.com
twitter/dan_abramov
github/gaearon
Зачем рендерить на клиенте?
-
Где-то рендерить надо
-
Дублировать UI-код непрактично
-
Стоимость фич не должна прыгать
-
Всё равно надо делать API
-
Есть срединный путь
-
MVC, MVP, MVVM, MVI, MMXV, MMM ...
-
Фабрики локаторов сервисов фабрик
-
Двусторонняя привязка данных
-
Мешать разметку с кодом
-
Инлайновые стили
-
Инлайновые обработчики событий
Лучшие Практики
Лучшие Практики
Лучшие Практики
Лучшие Практики
Лучшие Практики
Лучшие Практики
Почему веб-приложение это сложно?
Почему приложение это сложно?
Данные
Интерфейс
Global Events
Dirty Checking
Data Binding
Lifecycle
Routing
Persistence
Networking
Transactions
Animations
change:text
router:navigate
...
$(el).text()
app.replaceChildView()
...
change:text
router:navigate
...
$(el).text()
app.replaceChildView()
...
Сложность кода для обновления UI растет как квадрат количества его состояний
Наши интеллектуальные силы в основном связаны со статическими отношениями. Наши способности представлять процессы, развивающиеся во времени, гораздо слабее.
Как мудрые программисты, осознающие свои ограничения, мы должны делать все возможное, чтобы сократить концептуальную пропасть между статической программой и динамическим процессом.
Если UI это функция, что она возвращает?
Элемент DOM?
Строку?
Промежуточное представление!
Декларативное описание UI
И в чем разница?
Virtual DOM
Value DOM?
UI первого класса
Привычные средства абстракции
Компоненты
≈
Функции
Свойства — единственный API компонента
React.render и this.setState()
Разработчик
- Как преобразовать данные в UI?
- Как события из UI изменяют данные?
- Как разбить UI на независимые компоненты?
React
- Как эффективно перейти от одного UI-дерева к другому?
Интересные следствия
Малая поверхность API
Предсказуемость
Рендеринг не в DOM
Сохранение и восстановление состояния
Горячая загрузка
Нет «смерти от тысячи порезов»
Свобода от DSL
JSX?
Но это же DSL?
А как же разделение ответственности?
Что мы узнали
- Описывать динамические процессы сложно
- Описывать N*(N–1) переходов трудоемко
- Проще описывать статические «снимки» UI
- UI первого класса дает гибкость
- Баги будут — важна предсказуемость
Что мы узнали
- Чтобы знать React, надо знать JavaScript
- React это V, но «толстые» M и C не нужны
- React может работать в разных окружениях
- Можно использовать JSX
- Используется в продакшне Facebook, Airbnb, Reddit, Codecademy, Flipboard, Khan Academy, Yahoo, ...
Демо
Архитектура
Цель: Предсказуемость
Цель: Предсказуемость
Цель: Консистентность
Цель: Консистентность
Лучше, если данные «живут» где-то сверху и передаются вниз
MVC?
-
Гранулярные изменения не нужны
-
Есть механизм передачи данных вниз
-
Отлично сочетается с неизменяемостью
Сильные стороны React
-
Непредсказуемые каскадные обновления
-
Не сочетается с неизменяемостью
-
Сложно работать с циклическими и глубоко вложенными данными
Слабые стороны MVC
Flux
Global Events
Dirty Checking
Data Binding
Lifecycle
Routing
Persistence
Networking
Transactions
Animations
Global Events
Dirty Checking
Data Binding
Lifecycle
Routing
Persistence
Networking
Transactions
Animations
Компоненты
Данные
Как отвязать компоненты от знаний о внутренней структуре данных?
Промежуточное представление!
Не записывай,
а описывай.
{
type: "follow_user",
userId: 123
}
Хранилища
Компоненты
Действие
Изменение данных
Хранилища нельзя изменить напрямую
Store.getSomething()
Store.setSomething()
{
type: "follow_user",
userId: 50
}
Хранилища
Компоненты
Действие
Изменение данных
{
type: "like_post",
postId: 42
}
Хранилища
Компоненты
Действие
Изменение данных
{
type: "follow_user",
userId: 227
}
Хранилища
Компоненты
Действие
Изменение данных
Нет каскадов изменений
Много ко многим
Хранилища
Компоненты
Обновление UI
"changed"
Хранилища
Компоненты
Обновление UI
"changed"
Гранулярность на уровне хранилищ
Подписываться лучше выше и мало
Хранилища
Компоненты
Хранилища
Компоненты
{
type: "follow_user",
userId: 123
}
Хранилища
Компоненты
Действие
Трансляция действия компонентом
{
type: "follow_user",
userId: 123
}
Хранилища
Компоненты
Действие
Изменение данных хранилищами
Хранилища
Компоненты
Оповещение компонентов
Хранилища
Компоненты
"changed"
Оповещение компонентов
Хранилища
Компоненты
Обновление компонентами состояния
Хранилища
Компоненты
Обновление компонентами состояния
Хранилища
Компоненты
AJAX?
Все данные должны приходить из действий
Все изменения должны быть заключены в хранилищах
Интересные свойства
Предсказуемость
Предсказуемость
Запись и вопроизведение
Нормализация
Кросс-платформенность
Когда использовать Flux?
twitter/dan_abramov
github/gaearon
React как беспилотный автомобиль
By Dan Abramov
React как беспилотный автомобиль
- 4,477