-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathchapter1.tex
328 lines (209 loc) · 31.2 KB
/
chapter1.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
\chapter{Всё, что нужно знать о React}
Эта книга предполагает, что вы уже знаете, что такое React, и какие проблемы он может решить. Скорее всего вы уже пробовали его использовать и создавали небольшие приложения, и теперь хотите улучшить свои навыки и найти ответы на открытые вопросы.
Вы должны знать, что React поддерживается разработчиками Facebook и множеством участников JavaScript сообщества.
React - одна из самых популярных библиотек для создания пользовательских интерфейсов, которая достигает хорошей производительности благодаря оптимизированное работе с DOM (Document Object Model).
Вместе с React мы также получаем язык разметки JSX, который заставит вас изменить свое отношение к разделению ответственности. Также с ним идет множество полезных инструментов, например рендеринг на стороне сервера (server-side rendering), которое позволяет создавать Универсальные приложения (Universal web applications).
Для полноценного изучения книги вам нужны будут базовые навыки работы с терминалом для установки $npm$ пакетов.
Также все примеры кода будут написаны на стандарте ES2015 языка JavaScript, поэтому вы должны уметь читать его и понимать.
В этой главе мы разберем базовые концепции React, которые могут быть не очевидны начинающим разработчикам, но необходимые для эффективного использования библиотеки:
\begin{itemize}
\item Разницу между императивным и декларативным программированием
\item React компоненты и их экземпляры, а также, как React использует элементы для описания пользовательского интерфейса
\item Как React меняет подход к созданию web приложений, делая упор на концепцию разделения ответственности
\item Какие проблемы испытывают люди при разработке на JavaScript, и как вы можете избежать большинства распространенных ошибок при работе с React.
\end{itemize}
\section{Декларативное программирование}
Если вы будете читать документацию, статьи или блоги по React, то вы точно неоднократно встретите слово \textbf{декларативный}.
В декларативном подходе разработки на React кроется один из секретов его применимости.
Следовательно, для того, чтобы заниматься React профессионально, необходимо понимать разницу между императивным и декларативным подходами к разработке.
Один из простейших способов почувствовать эту разницу, думать об императивном программировании как о процессе описания "как что-либо должно работать", а о декларативном программировании как о процессе описания "что вы хотите получить в результате".
Мы можем провести параллель с реальной жизнью, например, с походом в бар. В этом случае поход в бар в императивном стиле будет выглядеть следующим образом:
\begin{itemize}
\item Возьмите стакан с полки
\item Поставьте стакан под кран бочки с пивом
\item Тяните ручку пока стакан не наполнен
\item Передайте мне стакан
\end{itemize}
В декларативном стиле вам потребуется сказать: "Пива мне".
Следуя декларативному стилю вы предполагаете, что бармен сам знает, как налить вам пиво. Это важный принцип декларативного программирования. Давайте посмотрим, как он работает на примере JavaScript.
Предположим, что нам нужно написать функцию, которая принимает единственным аргументом массив строк, а возвращает массив этих же строк, но в нижнем регистре:
\begin{lstlisting}
toLowerCase(['FOO', 'BAR']) // ['foo', 'bar']
\end{lstlisting}
В императивном стиле проблема может быть решена следующим образом:
\begin{lstlisting}
const toLowerCase = input => {
const output = []
for (let i = 0; i < input.length; i++) {
output.push(input[i].toLowerCase())
}
return output
}
\end{lstlisting}
Сначала будет создан пустой массив для хранения результата работы функции. Затем мы в цикле обходим строки, переданные функции, и добавляем их в нижнем регистре в созданный ранее массив. Затем мы возвращаем созданный массив как результат работы функции.
В декларативном стиле решение может выглядеть следующим образом:
\begin{lstlisting}
const toLowerCase = input => input.map(
value => value.toLowerCase()
)
\end{lstlisting}
В данном решении исходный массив передается в функцию $map$, которая принимает аргументом функцию преобразования элементов и сама создает результирующий массив.
Нужно обратить внимание на важное различие в двух вариантах кода: в первом случае код сложнее и труднее для восприятия, в то время как во втором случае он краток и выразителен. Это лишь пример одной функции. На масштабах большой кодовой базы такая разница сильно влияет на поддерживаемость проекта.
Помимо этого в декларативном варианте нет необходимости создавать переменные для хранения данных и изменять их значение в процессе работы функции. Таким образом декларативный подход помогает избежать создания, и что важно изменения множества сущностей.
И теперь давайте посмотрим, что значит для кода на React быть декларативным.
Решим часто встречаемую web разработчикам задачу: показать карту с маркером на ней.
Решение на JavaScript (с использованием Google Maps SDK) может выглядеть следующим образом:
\begin{lstlisting}
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng,
})
const marker = new google.maps.Marker({
position: myLatLng,
title: 'Hello World!',
})
marker.setMap(map)
\end{lstlisting}
Это достаточно императивное решение так как в коде мы напрямую используем все инструкции для создания карты, создания маркера и их объединению.
В свою очередь реализация на React выглядела бы следующим образом:
\begin{lstlisting}
<Gmaps zoom={4} center={myLatLng}>
<Marker position={myLatLng} Hello world! />
</Gmaps>
\end{lstlisting}
В данном случае мы лишь описывает, как должен выглядеть компонент, но не описывает детально все шаги для достижения этого результата.
\section{Элементы React}
В этой книге мы предполагаем, что вы уже знакомы с компонентами React и имеете представление о том, как их создавать и использовать. Но если вы хотите использовать React эффективнее вы должны знать еще об одной сущности: \textbf{Элемент (the Element)}
Независимо от того, используете ли вы \textit{createClass}, наследуете ли \textit{React.Component} или создаете компонент-функцию, вы создаете компонент. React управляет всеми компонентами во время исполнения программы и для каждого компонента может быть создано множество его экземпляров в один момент времени.
Как было сказано выше, React следует декларативной парадигме, и нет необходимости дополнительно описывать, как React должен взаимодействовать с DOM. Вам нужно лишь описать, что вы хотите увидеть на экране, и React сделает остальное за вас.
Если у вас есть опыт работы с другими UI библиотеками, то вы могли заметить, что они оставляют ответственность за обновление интерфейса на разработчике, который вынужден управлять созданием и удалением DOM элементов вручную.
Для поддержания UI в актуальном состоянии, React использует специальный тип объектов, \textbf{элемент(element)}, который описывает, что должно быть показано на экране. Это неизменяемый (immutable) объект, проще и легче компонент, и содержащий ровно ту информацию, которая необходима для отображения интерфейса.
Пример просто элемента выглядит следующим образом:
\begin{lstlisting}
{
type: Title,
props: {
color: 'red',
children: 'Hello, Title!'
}
}
\end{lstlisting}
В объекте содержатся тип элемента ($type$) и параметры. Также есть специальный опциональный атрибут $children$, в котором содержатся непосредственные потомки данного элемента.
Тип важен для элемента, так как он сообщает React, как обрабатывать данный элемент. Если тип является строкой, тогда React создает на его основе \textbf{вершину DOM} в DOM дереве, а если функцией, тогда React представляет его как \textbf{React компонент}.
DOM элементы и компоненты могут быть вложенными друг в друга для отображения дерева элементов:
\begin{lstlisting}
{
type: Title,
props: {
color: 'red',
children: {
type: 'h1',
props: {
children: 'Hello, H1!'
}
}
}
}
\end{lstlisting}
Если тип элемента -- функция, то React вызывает ее, передавая необходимые параметры, для получения нижележащих элементов. React проделывает эту операцию рекурсивно пока не получит все DOM вершины, которые React уже способен отрисовать на экране. Этот процесс называется \textbf{сверкой (reconciliation)} и используется и React Dom и React Native для построения пользовательского интерфейса.
\section{Забудьте, что вы знали}
Разработка на React принесла множество новых парадигм и приемов, сломав множество устоявшихся практик. Поэтому, если вы встречаете React впервые, вам нужно быть открытым к новым подходам в разработке.
Последние два десятилетия мы делали упор на разделении ответственности как на разделении логики и шаблонов. Мы всегда стремились писать HTML верстку и JavaScript код в разных файлах.
Чтобы помочь разработчикам достигнуть этой цели было создано множество шаблонизаторов.
Но проблема такого разделения в том, что на самом деле HTML и JavaScript все равно остаются сильно связанными. Посмотрим на небольшой пример:
\begin{lstlisting}
{{#items}}
{{#first}}
<li><strong>{{name}}</strong></li>
{{/first}}
{{#link}}
<li><a href="{{url}}">{{name}}</a></li>
{{/link}}
{{/items}}
\end{lstlisting}
Этот пример взят с сайта \textbf{Mustache}, одного из самых популярных шаблонизаторов.
Первая строка говорит Mustache, что необходимо обойти в цикле коллекцию элементов (items). Внутри цикла есть несколько условных операторов для проверки, что параметры $\#fist$ и $\#link$ существуют. И в зависимости от существования этих параметров отображаются разные куски HTML. Переменные находятся внутри двойных фигурных скобок.
Если вам нужно отрисовать содержимое лишь нескольких переменных, то шаблонизатор может быть хорошим решением. Но все сильно меняется, если вам нужно работать со сложными структурами данных.
По факту шаблонизаторы с их Предметно Ориентированными языками (Domain-Specific Language, DSL) предоставляют некоторый набор функций, пытаясь быть похожими на полноценные языки программирования, но абсолютно не достигая их полноты.
Как показано на примере выше, шаблоны сильно зависимы от формата данных, которые приходят с уровня логики. С другой стороны JavaScript все равно взаимодействует с DOM элементами, созданными шаблонизатором, для обновления UI.
Та же проблема относится к стилям: они определены в отдельных файлах, но шаблоны ссылаются на них, а CSS стили следуют структуре разметки. Невозможно изменить одно, не сломав другое, что говорит об их сильной связности.
Классическое разделение зависимостей в web является скорее разделением технологий, а не зависимостей. Это не плохо само по себе, но решает меньше задач, чем нам возможно хотелось бы.
React пытается сделать шаг вперед, чтобы перенести шаблоны ближе к логике. А разделение ответственности осуществляется посредством того, что React рекомендует разделять приложение на небольшие строительные блоки, \textbf{компоненты}.
Фреймворк не должен говорить вам, как разделить ваш код, поскольку каждое приложение имеет собственную структуру, и разработчики могут лучше решить, где стоит проводить линию между независимыми блоками.
Компонентно-ориентированный подход коренным образом меняет подход к созданию веб приложений, постепенно вытесняя старые методы.
Парадигма, продвигаемая React, далеко не нова и не была изобретена создателями библиотеки. Но заслуга создателей библиотеки в том, что они сделали этот подход более популярным, а также создали комфортное окружение, чтобы библиотекой смогло овладеть большое множество разработчиков с разным уровнем опыта.
Так выглядит метод $render$ React компонента:
\begin{lstlisting}
render() {
return (
<button style={{ color: 'red' }} onClick={this.handleClick}>
Click me!
</button> )
}
\end{lstlisting}
Поначалу этот код может выглядеть странным, но это ожидаемо, так как мы не привыкли использовать такой синтаксис.
Когда мы изучим его и разберемся в его возможностях, мы сможем понять его потенциал.
Использование JavaScript и для логики и для шаблонизации позволяет не только лучше разделить области ответственности кода, но и за счет большей выразительности позволяет создавать более сложные приложения.
Поэтому, даже если поначалу идея смешать в одну кучу JavaScript и HTML звучит для вас странно, стоит потратить немного времени для знакомства с React.
Один из лучших способов изучить библиотеку -- это сделать небольшое приложение и посмотреть как это работает. В общем случае всегда стоит быть готовым отбросить текущие навыки и изучить новые парадигмы, если это принесет пользу в будущем.
Следует обратить внимание, что есть один спорный момент относительно стилей. Основная цель этой идеи -- объединить все технологии создания web приложений внутри JavaScript для еще большей гибкости в разделении ответственности на основе логики приложения.
Посмотрим на пример создания стилей внутри JavaScript:
\begin{lstlisting}
var divStyle = {
color: 'white',
backgroundImage: 'url(' + imgUrl + ')',
WebkitTransition: 'all', // note the capital 'W' here
msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};
ReactDOM.render(
<div style={divStyle}>Hello World!</div>,
mountNode
);
\end{lstlisting}
Такой подход называется $\#CSSinJS$, подробнее о ней мы поговорим в Главе 7.
\section{Распространенные заблуждения}
Есть распространенное мнение, что React - это большой набор технологий и инструментов, и, если вы хотите использовать его, то вы вынуждены иметь дело с различными пакетными менеджерами, трансляторами кода, сборщиками бандлов и огромным множеством других библиотек.
Эта мысль настолько разошлась в массы, что даже получила собственное название \textbf{Усталость от JavaScript (JavaScript Fatigue)}.
В общем-то несложно понять, почему так происходит. Все новые репозитории и библиотеки в экосистеме React создаются с использованием новых технологий, последней версией JavaScript и продвинутыми практиками и парадигмами.
Кроме того, на GitHub появилось множество готовых заготовок проектов с десятками зависимостей для решения любой проблемы.
Очень легко начать думать, что все эти зависимости необходимы для разработки на React, но на самом деле это далеко от правды.
Вопреки этому мнению React является очень легковесной библиотекой и может быть использован на любой странице (даже в JSFiddle) таким же образом как jQuery или Backbone, просто добавлением скрипта в HTML код страницы.
Справедливости ради стоит сказать, что необходимо добавлять на страницу два скрипта, так как React разделен на две библиотеки: $react$ с ядром основной логики библиотеки, и $react-dom$ со специфичными для браузеров функции. Это было сделано для того, чтобы React мог использоваться в отличных от браузера средах, например c React Native на мобильных устройствах.
Запуск React внутри простой HTML страницы не требует дополнительных менеджеров пакетов и сложных телодвижений. Вам достаточно скачать пакет с React и разместить его у себя (или использовать $unpkg.com$). С этого момента вы можете пользоваться всеми возможностями React.
Для того, чтобы начать работу с React нужно добавить следующие две ссылки в HTML:
\begin{itemize}
\item https://unpkg.com/react/dist/react.min.js
\item https://unpkg.com/react-dom/dist/react-dom.min.js
\end{itemize}
Если мы добавим только библиотеку React, мы не сможем использовать JSX, который не является частью языка. Но основная цель -- начать работу с React с минимальным набором инструментов и расширять их по мере необходимости.
Для простого интерфейса мы можем использовать $createElement$, а транслятор JSX можно добавить лишь тогда, когда нам понадобится создать что-то более сложное.
Когда наше приложение будет становиться еще сложнее, нам может понадобиться роутер (router) для переключения страниц.
В какой-то момент нам может потребоваться загружать данные с различных API, наше приложение будет расти и нам могут потребоваться сторонние библиотеки. В этот момент можно подключить пакетный менеджер.
Затем нам скорее всего потребуется разделить приложение на различные модули, чтобы у проекта была понятная структура. В этот момент стоит задуматься о сборщике бандла.
Если следовать этим простым правилом, то усталость от JavaScript обойдет вас стороной.
Важно заметить, что любая область профессии разработчика (front end в том числе) требует непрерывного обучения. Web развивается семимильными шагами в соответствии с растущими требования пользователей и разработчиков. По такому принципу Интернет развивается с его появления и в том числе это добавляет ему великолепия.
Также удивительным является то, что с появлением новой спецификации языка, сообщество сразу создает транслятор новых возможностей в старые версии языка, позволяя разработчиком попробовать их до того, как они будут полноценно добавлены в браузеры.
Это то, что сильно отличает экосистему JavaScript и Web от других языков программирования.
Обратная сторона медали в том, что знания и инструменты устаревают очень быстро, поэтому следует искать баланс между новыми технологиями и безопасностью работы.
Но по крайней мере разработчики React беспокоятся об удобстве разработчиков и прислушиваются к мнению сообщества. Даже несмотря на то, что React не требует глубоко изучения множества инструментов для начала работы, создатели библиотеки осознали, что многим достаточно трудно сделать первые шаги в ее изучении, и выпустили консольное приложение для создания и запуска базового проекта, чтобы максимально упростить вход в React разработку.
Единственное требование -- наличие окружения с установленным \textit{node.js/npm}. С помощью него мы без проблем можем установить консольное приложение:
\begin{lstlisting}
npm install -g create-react-app
\end{lstlisting}
После установки приложения мы можем создать новый проект, запустив это приложение и передав название проекта:
\begin{lstlisting}
create-react-app hello-world
\end{lstlisting}
После этого мы можем открыть созданную папку командой \textit{cd hello-world} и запустить командой:
\begin{lstlisting}
npm start
\end{lstlisting}
Таким образом за пару шагов мы запустили полноценное React приложение с минимальным набором самых актуальных инструментов.
Мы будем использовать этот инструмент на протяжении всей книги для запуска примеров кода, которые можно найти на:
\href{https://github.com/MicheleBertoli/react-design-patterns-and-best-practices}{https://github.com/MicheleBertoli/react-design-patterns-and-best-practices}
\section{Заключение}
В первой главе мы посмотрели на базовые концепции React, которые понадобятся нам и на протяжении всей книги и в ежедневной разработке.
Теперь мы знаем, как писать декларативный код, и понимаем разницу между компонентами и элементами, используемыми React для отображения экземпляров компонент в браузере.
Также мы посмотрели, почему React пошел по пути объединения логики и шаблонов, и как это стало большой победой для React.
Помимо этого мы узнали про явление Усталости от JavaScript и поговорили немного о ее причинах и способах ухода от нее.
И в конце мы разобрались с консольным инструментом $create-react-app$, с которым мы сможем легко и быстро начать использовать React.