@samitouri / QOS-React / commits / dc60780d49

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` могут измениться после отрисовки родительского компонента.