Спешим вас порадовать — мы уже вовсю переводим книгу небезызвестного Стояна Стефанова о библиотеке React
Мы сочли, что этот молодой росток на массивном стволе JavaScript нелишне будет бережно прорекламировать, поэтому предлагаем почитать обзорную и слегка восторженную статью, которая, на наш взгляд, устарела всего на пару абзацев (их мы опустили)
React уже стал одним из самых перспективных протагонистов среди фреймворков JavaScript. Этот инструмент прост и удобен в работе, но, тем не менее, исключительно сложно четко сформулировать его достоинства, доказывая целесообразность React как такового. Даже сами авторы проекта признавали, что, приступая к его разработке, не вполне могли ответить на такие вопросы.
Два основных возражения в пику React таковы:
- Его неполнота?—?React не является “полностековым” фреймворском в отличие от Meteor или Angular. В нем нет маршрутизатора, системы моделей и многих других возможностей, которые положено иметь фреймворку. Говорят, что он реализует всего лишь “V” из MVC, но это далеко не так, о чем я и собираюсь поговорить.
- Его синтаксис?—?здесь смешаны HTML и Javascript. Программист смотрит на JSX и вопрошает: “но… зачем?”. А некоторые даже выступают за подмешивание CSS.
Я постараюсь осветить обе эти проблемы, а также заострю внимание на некоторых сильных сторонах React. Итак, поехали!
Итак, что же такое React?
React – это javascript-библиотека для создания компонентов. Каждый компонент обладает «внешним видом», который задается методом render и некоторыми состояниями, определяемыми в
getInitialState
. Внешний вид зависит от текущего состояния. Вот, в сущности, и все. И вот почему бывает так сложно объяснить React – у многих он вызывает именно такое ощущение «неполноты».Пример:
Counter = React.createClass
getInitialState: ->
count: 0
increment: ->
@setState(count: @state.count + 1)
render: ->
<div>
{ @state.count }
<button onClick={ @increment }>+</button>
</div>
В этом примере у нас есть кнопка, при нажатии на которую вызывается метод инкремента. Метод
increment
вызывает setState, таким образом, задается новое число, на единицу больше текущего.Метод
setState
вновь отображает компонент. Это делается настолько оригинально, что именно в этом React и его клоны отличаются от аналогичных инструментов. В сущности, React хранит в памяти объектную модель документа, именуемую «виртуальной DOM» («теневая DOM» — немного другой феномен), а затем вычисляет разницу между этой DOM и той, что отображена в браузере. На основании этой разницы составляется список изменений, которые необходимо внести – представьте себе createElement
– а затем эти изменения применяются.Разумеется, в React придется познакомиться и со многими другими концепциями — например, свойства (props), различные атрибуты тегов – но наиболее важна именно DOM.
В чем упрекают React
Неполнота. Плохо или хорошо?
Когда появились Rails, в них особенно рекламировалась их «полностечность» (надеюсь, есть такое слово). С тех пор ни одна из альтернатив не получилась столь же самодостаточной – ведь в Rails есть и уровень абстрагирования базы данных, и система маршрутизации, и шаблонизатор, и т.д.
Насколько мне известно, первой из альтернатив стал Camping от Why – микрофреймворк, состоявший из считанных строк кода. За ним последовали Sinatra, CherryPy, Flask, Express и многие другие. Но дело в том, что все они продолжают эмулировать концепцию фреймворка, просто получаются немного тоньше, а также написаны менее предвзято. А продаются эти инструменты благодаря тому, что с ними не так много возни и, соответственно, они более удобны для разработки сравнительно мелких приложений.
Та неполнота, которой отличается React, принципиально иная. React – не просто облегченный Angular, а нечто принципиально иное. Он очень хорошо справляется с конкретной задачей: работает с веб-компонентами. Итак, неверно рассуждать о том, какого размера должен быть наш проект. Кстати, React делался с упором на производительность, именно на нем работает система комментариев в Facebook – следовательно, он вне всяких сомнений способен работать в колоссальных масштабах.
Вот о чем стоит задуматься: а нужен ли вам полновесный фреймворк и, кроме того, сможете ли вы организовать все необходимые компоненты на базе React. Во-первых, следует отметить, что размер машинного интерфейса, в сущности, не важен. Если вам приходится загружать фреймворк размером 1ГБ, но на выходе получается гибкое и быстрое приложение, то это не проблема. С другой стороны, размер фронтенда очень важен. Любая дополнительная нагрузка от вашего фреймворка сразу повлияет на конечный результат.
Есть в React и другие замечательные возможности, благодаря которым он воспринимается как полноценный фреймворк. Мне известно много примеров подмешивания моделей Backbone в React. Есть и отличные библиотеки для добавления маршрутизации. Но одно из основных достижений сообщества React – это, конечно, Flux, хотя это и не столько набор инструментов, сколько подход к архитектуре приложения.
Правда ли, что React – всего лишь V из аббревиатуры MVC?
Как отмечает Андрэ Медейрос в своей великолепной презентации, возможности React далеко не ограничиваются V. Дело в том, что у компонентов React есть состояние, поэтому такой компонент – в некотором смысле Модель. Он обеспечивает отображение ввода на изменение состояния, поэтому, в то же время, имеет черты Контроллера, или даже Представления, подчеркивает Медейрос. Компонент также обменивается информацией с другими компонентами и зависит от них. Итак, вам не придется искать подходящие библиотеки для модели и контроллера – подобное мнение попросту ошибочно.
А поскольку React содержит все эти вещи в виде цельной концепции – компонента – в нем открываются широчайшие возможности писать беспорядочный сильно связанный код, в котором плохо реализовано разделение ответственности.
Медейрос предлагает решать эти проблемы, взяв на вооружение принцип MVI?—?Модель-Вид-Намерение?—?то есть, пропагандирует довольно своеобразный подход к веб-разработке. Одна из реализаций этого подхода называется Цикл.
Зачем смешивать HTML и JS? …Что? И CSS тоже???
Десять лет назад в веб-разработке была своя священная корова – разделение HTML, JS и CSS. Все три технологии должны были существовать сами по себе, в отдельных файлах и каталогах. Эти файлы могли только ссылаться друг на друга, что делалось при помощи включений.
Как ни гармонично выглядит такое разделение, это всего лишь разграничение технологий, но не ответственности. React ставит под сомнение такой подход, четко регламентируя, что разделение должно происходить на уровне компонентов. В компонентах могут смешиваться разные технологии, но каждый из компонентов – хорошо инкапсулированный и подогнанный элемент, он логично выглядит и логично функционирует. Если в рамках такого функционала задействованы различные технологии и языки – так тому и быть.
Все это может вызывать отторжение, которое, на мой взгляд, объясняется чистейшими необоснованными предрассудками. Всего через несколько часов привыкаешь. Все мнения о React, которые я нашел в Интернете, в сущности, одинаковые. Вдруг избавляешься от необходимости держать два открытых файла в соседних вкладках — и продуктивность работы резко возрастает.
Некоторые даже выступают за то, чтобы полностью перенести CSS в область компонента. Прежде, чем клеймить меня, посмотрите интересную презентацию на эту тему от Кристофера Чедау.
Аргументы в защиту React
Здесь есть экосистема.
Я пишу эту статью, а React только что обошел Ember по рейтингу на GitHub. Он уступает Backbone и, естественно, Angular, но растет гораздо быстрее «конкурентов».
React – это проект Facebook, именно на нем реализована система комментирования в Facebook и большинство проектов этой компании. Кроме того, React широко применяется в Pinterest, AirBnB, Khan Academy и на массе других стартапов. На основе React выстроен редактор Atom, более того, и Microsoft поддерживает React.
Тем самым я пытаюсь доказать, что React – уже мейнстрим, насколько вообще можно говорить о мейнстриме в технологическом ландшафте инструментов JavaScript. Это означает, что вам не придется особо беспокоиться о поддержке проекта, о том, обрастет ли он экосистемой. Уже можно убедиться, что существует туча библиотек для React – хотя, пока мне и сложно судить об их качестве.
Проще судить о коде
Один из основных аргументов в пользу React связан с его логичностью. Это предельно верное утверждение, и нельзя недооценивать его весомость и важность.
Судить о коде, на мой взгляд — это не просто уметь вычленять в нем слабо и сильно связанные участки. Это значит, логически следовать от осознания проблемы к пониманию того, где и что происходит (события, потоки данных…), быстро оценивать эти элементы и, наконец, устранять проблему.
Интересная вещь: задумываясь о качестве программы, нужно обращать внимание не только на количество багов – у нас в Agile вообще проповедуется идея, что «никаких багов быть не должно» — но и на то, сколько времени потребуется на устранение бага. Усвоив эту идею, я вспомнил баг, который удалось изжить только через год. Он учинял чудовищные утечки памяти и значительно тормозил всю программу, особенно при пиковых нагрузках. Если исходить лишь из количества багов, то, вполне возможно, у вас будет всего горстка таких изъянов, но само решение при этом все равно окажется очень плохим.
Итак, длительность устранения бага свидетельствует о том, сложно ли судить о коде. Если на устранение бага уходит много времени, это означает, что разработчикам приходится изрядно покорпеть над проблемой, прежде, чем она обнаружится – и наоборот.
React упрощает рассуждение о коде, причем сразу по нескольким причинам. Основная –DOM без сохранения состояния. Для примера рассмотрим, как в традиционной jQuery реализуется переключение:
// html
<section>
<div class="toggled">HERE I AM</div>
<button class="toggler">Toggle!</button>
</section>
// coffescript
$('.toggler').on 'click', ->
$('.toggled').toggle()
На первый взгляд, все просто. Но вот в чем загвоздка: а как вы узнаете, отобразился ли div? Да, можно сказать: «Если нажать на кнопку button любое четное количество раз, то он отобразится, а если нет – не отобразится”.
Toggler = React.createClass
getInitialState: ->
visible: true
toggle: ->
@setState(visible: !@state.visible)
render: ->
<section>
{ @state.visible && <div>HERE I AM</div> }
<button onClick={ @toggle }>Toggle!</button>
</section>
А теперь ситуация радикально меняется. Можно сказать: «Он отображается, если виден». Железное правило: если ваш код удобен для понимания, то выразить что-либо в этом коде можно гораздо яснее.
Переиспользование
Это волшебное слово. В мире бэкенда переиспользование фрагментов кода – реальность. Речь может идти, например, о самоцветах или яйцах. Но в клиентской части может показаться, что для каждого нового проекта все приходится пересобирать заново. Действительно, такие вещи, как инструмент обхода DOM или URL-парсер переиспользовать легко, но когда дело доходит до контента как такового, каждый проект начинает выглядеть по-своему, а каждый элемент макета – сама оригинальность, которая не лезет «под одну гребенку».
Признаюсь, я еще не встречал, чтобы компоненты перекочевывали из одного проекта в другой, но не вижу никаких причин, почему бы атомарные сущности вроде окон с уведомлениями и кнопок, и даже более «молекулярные» или «органические» вещи, например, статьи или списки задач не могли использоваться «как есть», если вы отделяете визуальное оформление от разметки и поведения.
Было бы интересно увидеть многократное использование одних и тех же разработок в разных компаниях, посмотреть, как люди будут писать свободные библиотеки с реализованными компонентами. Хороший пример — MaterialUI.
Выращивание проекта
Многие проекты для клиентской части, над которыми мне доводилось работать, вначале были совсем маленькими, а затем существенно вырастали. Некоторые претерпевали рефакторинг и приобретали совершенно иную структуру, либо в какой-то момент в них внедрялась импровизированная структура, которая должна была помочь справиться с нарастающей сложностью. В обоих случаях такая работа требует немало времени и усилий – впрочем, как и любой важный рефакторинг, позволяющий впоследствии значительно ускорить разработку.
Одна важная черта разработки на основе компонентов заключается в том, что она очень органично сочетается с этими стадиями эволюции проекта. Не могу себе представить, чтобы проект, начавшийся с небольшого набора компонентов и аккуратно организованного потока данных, потребовал таких радикальных изменений – ведь все его части очень стабильны.
Вот и все. Собственно, здесь я почти не затронул тему Flux, но это уже материал для совершенно другой статьи.
Комментарии (17)
jrip
02.12.2016 13:27+1Десять лет назад в веб-разработке была своя священная корова – разделение HTML, JS и CSS
React ставит под сомнение такой подходОчередной виток спирали,
улыбаемся и машем, в ряде задач вполне себе прикольно.
ripreal
02.12.2016 13:47-2Зачем переводить программисткие книги? Неужели есть те такие, кто занимаются такими специфическими Фреймворками, но при этом не обладают хотя бы intermidiate english-ом для чтения?
faiwer
02.12.2016 14:31+1Я думаю >90%, если даже не 95% русскоязычного web-сообщества не владеют английским на уровне "хотя бы intermediate". Это довольно серьёзный уровень, кстати говоря. У большинства или beginner или pre-intermediate. Второго, кстати говоря, уже хватает на чтение документации со словарём. Но времени и напряжения уходит куда больше, чем при чтении переводов. Но опять же, обычно переводов попросту нет, либо же их качество оставляет желать лучшего. Так, что изучение английского до уровня upper-intermediate или advanced в любом случае очень стоящая затея. Что, впрочем, нисколько не отменяет оторванности вашей реплики от реальности.
virtyaluk
02.12.2016 15:53Ну, о «intermidiate english-ом» вы, конечно, загнули. Но, вполне согласен с основной идеей.
Сам уже 2 разы натыкался на такую проблему, что брал книжку всего-лишь годичной давности, читал, делал по ней примеры. Потом садился за последнюю версию либы, о которой читал книжку, а там уже все по другому. И это, кстати, было с книжкой по Реакту и книжкой по Эмберу. В итоге сделал для себя выводы, что та-же документация (и по реакту и по эмберу) покрывает все на 100%. Тем более, когда книжка в топику вышла в середине лета, а за ее перевод взялись только сейчас.
Но затея, конечно же, хорошая. Русскоязычное сообщество и так отстает от последних тенденций. Но лично я бы рекомендовал переводить более «глобальные» книги по топику, тот-же последний JavaScript в книжках Кайла Симсона или Николаса Закаса.
404
02.12.2016 15:34+5Пожалуйста, перед публикацией отдайте перевод на вычитку техническому специалисту, причём работающему с реактом. Потому что уже устал догадываться, что имелось в виду читая ваши переводные книги.
Amunet
04.12.2016 18:29+1
уже сто лет как никто не пишет. Если хотие чтобы не просто переести книгу ну и продать ее, переведите все примеры на ES6/7.React.createClass
justboris
05.12.2016 12:04+1не сто лет, а года полтора.
Тренды веб-разработки меняются так быстро, перевод и издание занимает намного больше времени.
переведите все примеры на ES6/7.
А заодно может и пару новых глав добавить? Тогда это получится вообще новая книга, а не перевод.
Kanumowa
05.12.2016 11:53За перевод спасибо, но пожалуйста будьте оперативнее в Веб разработке, на англ эта книга вышла полгода назад, многое уже поменялось, например мы привыкли к ES6. Если будут выходить книги по Ангуляру 2, не ждите полгода :) и да, учите английский, ведь переводится только малая часть на русский язык :)
mayorovp
С необходимостью хранить состояние отдельно я согласен — но пример выбран крайне неудачно.
andrewsch
поддерживаю — очень неудачный пример
Вместо прозрачного и понятного HTML + JS (каждый на 2-5 строк) — приличный кусок кода, который приходится анализировать и вдумываться — а что оно делает… даже не смотря на некоторое знакомство с React
MikailBag
https://github.com/jquery/jquery/blob/2d4f53416e5f74fa98e0c1d66b6f3c285a12f0ce/src/css/showHide.js#L89
Код $#toggle() занимает примерно столько же, сколько и компонент.
К тому же, в реальности логика не каждого компонента будет "решаться" существующими библиотеками.
MikailBag
Не понимаю, за что минус.
mayorovp
Почему вы решили посчитать сколько места занимает реализация toggle — но не считаете сколько места занимает реализация React?
Ну так и надо было брать задачу, которая не решается существующими библиотеками. Почему такую задачу должен искать читатель?
MikailBag
согласен
Представим, что готовой реализации нет.
Тогда Вы напишете что-то вроде
Несильная разница в кол-ве кода, которая компенсируется более простым внедрением возможностей.
Кстати, весь код jQuery я тоже не считаю
mayorovp
Эдак можно представить что в языке нет XMLHTTPRequest и предложить свою реализацию на основе COM-объекта — но смысла в подобной аргументации будет мало :)
У нас уже есть jquery, и в нем есть toggle. Если автор уговаривает перейти с jquery на react — он должен привести аргументы, выходящие за рамки "представьте что у вас нет jquery".