Введение в React и Redux для бекенд-разработчиков

39971463536a4a83925bf3e8f46039ca.png
Если вы как я долгое время считали, что JavaScript — это такой «игрушечный» язык на котором пишут анимашки для менюшек и падающий снежинки на форумах под новый год, а потом очнулись в 2016 году с мыслями WTF: react, flux redux, webpack, babel, … не отчаивайтесь. Вы не одиноки. Материалов по современному фронтенду в сети много, даже слишком много. Под катом еще одно альтернативное мнение о том, каково это учить JavaScript в 2016 году.

Итак, нам потребуются: React, React Dev Tools, React-Hot-Loader, React-Router, Thunk, Redux, Redux Dev Tools, Semantic-UI, Webpack, Babel и npm.

На первый взгляд много. Сравним с бекендом: MVC-фреймворк, ORM, Data Mapper, IOC-контейнер, логер, профайлер, очереди, управление конфигурациями, сборка и выкладка… Список можно продолжить, но думаю идея понятна и так: с ростом сложности решаемых задач растет и сложность инструментов. Все чаще мы употребляем термин Web App вместо Web Site, акцентируя внимание на богатых возможностях современных веб-приложений.

Почему именно этот стек?


Если вдуматься и отбросить все лишнее, то единственный ресурс постиндустриальной эпохи, через который можно выразить все остальные — это время. Освоение каждой новой технологии требует затрат времени, а значит более перспективны инвестиции в технологии, которые не устареют в ближайшие пару месяцев. Дополнительный плюс получают технологии с пологой кривой обучения.

React + Redux VS Angular VS Yet Another JS Framework


Только ленивый не сравнил Angular с React«ом (приписав при этом, дескать, сравнение не корректно, Angular — фреймворк, React — библиотека). Пойдем от обратного. Почему бы не выбрать что-нибудь эдакое, типа Vue, Ember или, упаси боже, Elm?
  1. Поддержка крупных вендоров
  2. Размер сообщества

Благодаря этим факторам, вероятность выживания Angular и React выше. Простите, другие замечательные хипстерские решения, нам не по пути. Итак, почему React? Лично для меня выбор был не простым:
  1. Меня пугали jsx-файлы
  2. Я кое-что умел на Angular 1.x и переходить на другую технологию было психологически не комфортно
  3. ng2 по-умолчанию идет в комплекте с TypeScript, что мне как стороннику статической типизации ближе
  4. ng подкупал подходом «работает из коробки». Копаться в многообразии npm-пакетов решительно не хотелось.

Короче, я заставил себя изучить все статьи-сравнилки и написать Todo App на React, что склонило чашу весов в противоположную сторону. Ключевыми факторами для меня стали:
  1. HTML-шаблоны Angular — ужасны и их синтаксис меняется от версии к версии. В React шаблон — это JavaScript, потому что компонент — не более чем View. Сообщения об ошибках в React лучше.
  2. Как ни странно, TypeScript. При более детальном изучении оказалось, что не все так прекрасно. Во-первых TypeScript — это не полноценный язык со статической типизацией, а транспилер. Это сильно ограничивает возможности использования шаблонов и мета-программирования. Во-вторых, далеко не все npm-пакеты идут в комплекте с d.ts-файлами. Короче, Flow показался проще в прикручивании. В-третьих, у TypeScript есть как ярые фанаты, так и противники. Если фанаты TS сравнительно лояльны к ES6, то обратное — не верно. ES6 получает дополнительное очко к Bus Factor.
    Если вам нравится TypeScript, ничто не мешает использовать его вместе с React. Просто конкретно мне он пока не дал критического объема преимуществ, чтобы заставить тратить время на еще один элемент в стеке.
  3. Доклад Дэна Абрамова про «путешествия во времени». Если ваш опыт в бекенде похож на мой, то вы без труда увидите, что новомодный flux — это CQRS и Event Sourcing «вид в профиль». Вместо проекций — редюсеры, а вместо команд и доменных событий — экшны. А если вы работали, например, с WPF, то разобраться с React — вообще дело пары вечеров.
    Да, Redux можно использовать и с Angular, он никак не привязан к React, но для React уже есть react-redux и react-hot-loader. Наверное, для Angular тоже есть, но мейнтейнер Redux«а явно на стороне React.

Для React и Redux доступно два расширения Chrome. Рекомендую поставить оба, чтобы сделать отладку приятной.

Таким образом, связка React + Redux:

  1. Более-менее проста в изучении, потому что в основе лежит простая идея ui = f(state => props), где f — это реакт-компонент, state — redux, а state => props — это react-redux.
  2. Не тащит за собой дополнительных зависимостей
  3. Обладает лучшим на данный момент Tool Support (IDE и плагины для Chrome)

Есть еще всякие ништяки, вроде React Native, но я им не пользовался, поэтому поделиться на эту тему мне, к сожалению, нечем.

А flux и все эти модные словечки. Как это работает?


Возможно, для фронтенда flux — это некое откровение. Для бекендщика разница между CQRS и flux — не велика. React — это наше представление. Оно может зависеть от props (read-only) или state (mutable). В зависимости от state и props компонент может отображаться по-разному. Эта логика содержится в методе render. Компонент сам себя не перерисовывает. Вместо этого, он полагается на экосистему React. Мы можем либо изменить свое состояние (с помощью метода setState), либо быть перерисованными извне (переданы новые props). Обработчики событий для UI-элементов передаются через props. Получается такой код

Комментарии (19)

  • 11 апреля 2017 в 03:56

    –11

    >node
    > 0.1*0.1
    0.010000000000000002
    > 0.1*0.2
    0.020000000000000004
    > 0.1*0.3
    0.03
    > 0.1*0.4
    0.04000000000000001
    > 0.1*0.5
    0.05
    > 0.1*0.6
    0.06
    > 0.1*0.7
    0.06999999999999999
    > 0.1*0.8
    0.08000000000000002
    > 0.1*0.9
    0.09000000000000001
    

    У меня все.
    • 11 апреля 2017 в 04:02

      +11

      IEEE 754


      У меня всё.

    • 11 апреля 2017 в 04:09

      +2

      Что все? Это IEEE 754, во всех языках, которые его используют так будет.

      А статья — очередное «вступление в мир моды на быдлокод в JS», которых, как сам автор сказал, уже очень много и потому не нужна

    • 11 апреля 2017 в 04:22

      +2

      golang:
      package main
      import "fmt"
      
      func main() {
      	var a float32 = 0.1
      	var b float32 = 0.1
      	fmt.Println(a * b)
      	b = 0.9
      	fmt.Println(a * b)
      }
      

      > 0.010000001
      > 0.089999996
      
    • 11 апреля 2017 в 06:46

      +2

      Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]
      
      1> 0.1 * 0.1.
      0.010000000000000002
      2> 0.1 * 0.2.
      0.020000000000000004
      3> 0.1 * 0.3.
      0.03
      4> 0.1 * 0.9.
      0.09000000000000001
      
      
    • 11 апреля 2017 в 08:21 (комментарий был изменён)

      0

      D:


      import std.stdio;
      
      void main()
      {
          writeln( 0.1 + 0.2 ); // 0.3
          writeln( 0.1 + 0.2 == 0.3 ); // true
      }
  • 11 апреля 2017 в 08:31

    0

    > Первую задачу решает react-router. Здесь альтернатив нет
    react-router-redux?
    • 11 апреля 2017 в 08:49

      0

      Разве эта библиотека — не построена поверх react-router? Мне казалось, что она просто дополнительно пропускает переходы через store, чтобы сохранить time travel. Нет?
  • 11 апреля 2017 в 08:39

    0

    Как короткое описание своего технологического стека c возможностью изучать тему «вглубь» по ссылкам — статья понравилась.
    Немного критики. К сожалению, ряд моментов режет глаз.
    Сравним с бекендом: MVC-фреймворк, ORM, Data Mapper, IOC-контейнер…
    Почему MVC? Почему фреймворк? Почему ORM? И т.д. Это вовсе не необходимые компоненты бэкенда. Я бы назвал их «модными», но бэкенд может быть построен на совершенно других принципах. Кмк, такое сравнение тут не совсем к месту.
    Самым монструозным из всех был конечно Smarty. Мне казалось, что люди сошли с ума. Как иначе можно было объяснить желание написать шаблонизатор… для шаблонизатора Perl?
    Конечно же автор имеет в виду php, а не perl. Фраза о «шаблонизаторе для шаблонизатора» тоже модная, но слишком часто используется не в тему.
    • 11 апреля 2017 в 08:48

      +2

      Автор действительно имеет в виду Perl — первая версия PHP была написана на Perl и под его сильным влиянием. $ перед каждой переменной? Это из Perl!
      • 11 апреля 2017 в 09:02 (комментарий был изменён)

        0

        первая версия PHP была написана на Perl
        Это шутка что ли или я туплю? Насколько мне помнится, php/fi сразу был написан на C.
        Исправление… Понял о чем вы, о первом наборе скриптов на perl.
    • 11 апреля 2017 в 08:53

      0

      Почему MVC? Почему фреймворк? Почему ORM? И т.д. Это вовсе не необходимые компоненты бэкенда. Я бы назвал их «модными», но бэкенд может быть построен на совершенно других принципах. Кмк, такое сравнение тут не совсем к месту.

      Потому что примерно 90% кода из мира веб-разработки, который я видел или поддерживал — это MVC-фрейворк + ORM и не более. На PHP — это чаще всего Active Record, на Java — Hibernate, на .NET — Entity Framework. Да, бывают другие стеки. Но мейнстрим — именно ORM + MVC = love
  • 11 апреля 2017 в 09:13

    0

    Как по мне, то для разработчика MV* ООП веб-бэкендов, не стоит начинать свой путь во фронте с React+Redux, достаточно одного React, или React+MobX, если практикуешь DDD. Redux — это полное разделение состояния и поведения, а не их инкапсуляция в объектах.

    • 11 апреля 2017 в 09:28

      0

      Action’ы redux’а — это же не доменные объекты, а скорее просто message. Что мешает ловить экшны, создающие эффекты в middleware, обрабатывать в любом удобном виде, в т.ч. с применением DDD и по завершению операции выбрасывать DomainEventSucceeded / Failed и уже их обрабатывать в редюсерах?
      • 11 апреля 2017 в 09:50

        0

        Доменные объекты инкапсулируют данные и поведение. Redux же их разделят по крайней мере на уровне рекомендуемых практик. Может и можно технически хранить в store полноценные объекты с методами, реализующими доменное поведение, а потом дергать их в редюсерах, но точно это будет шоком для подавляющего большинства активно использующих Redux. А скорее всего эта возможность либо просто заблокирована (может только в дев-режиме), либо ожидаемой реакции на вызов методов объекта не будет, поскольку redux+react не заметят, что изменилось состояние объекта в редьюсере, поскольку ожидает либо возврат того же объекта без изменений, либо нового объекта. В общем не прокатит что-то вроде (state, value) => state.domainObject.setValue (value).


        Можно отдельно вынести мутабельную модель и проецировать её состояние на redux-стор в миддлварах, но что нам это даст, кроме «потому что можем»?

      • 11 апреля 2017 в 09:51

        0

        Мешает экпоненциальная костыльность «современной front end разработки» :-)

  • 11 апреля 2017 в 10:13

    0

    Почем нет ни слова про mobX? Мы же в 2017
  • 11 апреля 2017 в 10:25

    0

    Где relay?
  • 11 апреля 2017 в 10:30

    0

    Про reselect забыли!

© Habrahabr.ru