Create 03-interactivity-and-dynamic-uis.ru-RU.md
Andrey Safronov committed
May 4, 2016 at 10:01 UTC
dc60780d490280953eeabca34d7b663730dcd981
1 file changed
+78
docs/docs/03-interactivity-and-dynamic-uis.ru-RU.md
new
+78
@@ -0,0 +1,78 @@
1
+---
2
+id: interactivity-and-dynamic-uis
3
+title: Интерактивные и динамические интерфейсы
4
+permalink: interactivity-and-dynamic-uis.html
5
+prev: jsx-gotchas.html
6
+next: multiple-components.html
7
+---
8
+
9
+Вы уже знаете [как показывать данные](/react/docs/displaying-data.html) с React. Теперь давайте добавим в наши интферфейсы немного интерактивности.
10
+
11
+## Простой пример
12
+
13
+```javascript
14
+var LikeButton = React.createClass({
15
+ getInitialState: function() {
16
+ return {liked: false};
17
+ },
18
+ handleClick: function(event) {
19
+ this.setState({liked: !this.state.liked});
20
+ },
21
+ render: function() {
22
+ var text = this.state.liked ? 'like' : 'haven\'t liked';
23
+ return (
24
+ <p onClick={this.handleClick}>
25
+ You {text} this. Click to toggle.
26
+ </p>
27
+ );
28
+ }
29
+});
30
+
31
+ReactDOM.render(
32
+ <LikeButton />,
33
+ document.getElementById('example')
34
+);
35
+```
36
+
37
+## Обработка событий и псевдособытия
38
+
39
+С React вы просто передаете функцию-обработчик нужного события как аргумент, почти также, как делали это в HTML. А с помощью механизма псевдособытий, React гарантирует, что все события будут вести себя одинаково во всех браузерах. Действительно, React умеет работать с событиями при их всплытии и перехвате. И все события, которые попадут в обработчик будут вести себя в соответствии со [спецификациией W3C](http://www.w3.org/TR/DOM-Level-3-Events/), при этом неважно каким браузером вы пользуетесь.
40
+
41
+## Что внутри: автоматичсекое связывание и делегирование событий
42
+
43
+Чтобы ваш код был не только понятным, но и быстрым, React делает слудующее:
44
+
45
+**Автоматическое связывание:** Когда в JavaScript создаются функции-колбэки, вам надо привязать метод к тому объекту, на котором он будет вызываться, так чтобы значение `this` было корректным. С React привязка метода к компоненту происходит автоматически ([кроме тех случаев, когда вы используете классы ES6](/react/docs/reusable-components.html#no-autobinding)). И делается это с минимальной нагрузкой на процессор и память.
46
+
47
+**Делегирование событий:** На самом же деле, React добавялет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает кому из обработчиков его передать. Когда в памяти больше не остается обработчиков, они перестают работать. Если хотите узнать о том, почему такая механика так быстро работает, посмотрите [отличный пост в блоге David Walsh](http://davidwalsh.name/event-delegate).
48
+
49
+## Компоненты как конечные автоматы
50
+
51
+React считает интерфейсы обыкновенными конечными автоматами. Работать с интерфейсом становится проще, если представлять его как конечный автомат, который меняет состояния и отрисовывает их.
52
+
53
+В React вы просто обновляете состояние компонента, а потом выводите новый интерфейс уже с новыми данными. Все изменения в DOM-дереве React сделает сам, причем наиболее эффективным способом.
54
+
55
+## Как работает состояние
56
+
57
+Чтобы сообщить React о том, что данные изменились, вы вызываете метод `setState(data, callback)`. В этом методе происходит обновление состояния `this.state` новыми данными из `data`, и компонент отрисуется заново. После этого, вызывается функция `callback`. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.
58
+
59
+## В каких компонентах хранить состояние?
60
+
61
+Большинство компонентов должны просто брать данные из `props` и отрисовывать их. Но иногда вам надо реагировать на действия пользователя, делать запросы на сервер или просто сделать что-то по таймеру. В таких случаях используйте состояние.
62
+
63
+**Старайтесь делать компоненты без состояния.** Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, снижать сложность приложения, упрощая его понимание.
64
+
65
+Основной принцип такой: создаются несколько компонентов без состояния, которые формируют дерево. Они будут заниматься только отрисовкой данных. А все данные для них будут у родительского компонента, который будет на вершине этого дерева компонентов. Он и будет передавать данные дочерним узлам через `props`. Этот компонент с общим состоянием содержит в себе всю логику взаимодействия, а дочерние компоненты будут только отрисовывать данные, которые будут у них в `props`.
66
+
67
+## Какие данные *надо* помещать в состояние?
68
+
69
+**Состояние должно содержать данные, которые нужны для обновления интерфейса.** В реальных приложениях такие данные крайне малы и передаются, обычно, через JSON-файлы. Когда создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода `render()` вычисляйте остальные данные, используя значения из состояния.
70
+Со временем вы увидите, что написание приложений таким способом позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.
71
+
72
+## Какие данные *не надо* помещать в состояние?
73
+
74
+Состояние `this.state` должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит ложить туда:
75
+
76
+* **Вычисляемые данные:** Вам не надо думать о тех данных, которые надо вычислять через данные состояния — лучше позаботьтесь об интерфейсе, а все вычисления делайте в методе `render()`. Например, если в состоянии хранится список элементов и вам надо вывести его размер в виде строки. Напишите `this.state.listItems.length + ' элементов'` в методе `render()`. Это будет правильнее, чем хранить размер списка в состоянии.
77
+* **Компоненты React:** Создавайте их в методе `render()` опираясь на данные из `props` и `this.state`.
78
+* **Значения, повторяющие `props`:** старайтесь использовать `props` только как источник данных для отрисовки. Хранить значения `props` в состоянии допускатеся, только если вам надо где-то хранить их прошлые значения, ведь `props` могут измениться после отрисовки родительского компонента.