С React вы просто передаете функцию-обработчик нужного события как аргумент, почти также, как делали это в HTML. А с помощью механизма псевдособытий, React гарантирует, что все события будут вести себя одинаково во всех браузерах. Действительно, React умеет работать с событиями при их всплытии и перехвате. И все события, которые попадут в обработчик будут вести себя в соответствии со [спецификациией W3C](http://www.w3.org/TR/DOM-Level-3-Events/), при этом неважно каким браузером вы пользуетесь.
С React вы просто передаете функцию-обработчик нужного события как аргумент, почти также, как делали это в HTML. А с помощью механизма синтетических событий, React гарантирует, что все события будут вести себя одинаково во всех браузерах. Другими словами, React знает, как работает всплытие и перехват событий по спецификации. События, которые он передает в ваши обработчики, будут соответствовать [спецификации W3C](http://www.w3.org/TR/DOM-Level-3-Events/), и неважно каким браузером вы пользуетесь.
## Что внутри: автоматичсекое связывание и делегирование событий
## Что внутри: автоматическое связывание и делегирование событий
Чтобы ваш код был не только понятным, но и быстрым, React делает слудующее:
Чтобы ваш код был не только понятным, но и быстрым, React делает следующее:
**Автоматическое связывание:** Когда в JavaScript создаются функции-колбэки, вам надо привязать метод к тому объекту, на котором он будет вызываться, так чтобы значение `this` было корректным. С React привязка метода к компоненту происходит автоматически ([кроме тех случаев, когда вы используете классы ES6](/react/docs/reusable-components.html#no-autobinding)). И делается это с минимальной нагрузкой на процессор и память.
**Автоматическое связывание:** Когда в JavaScript создаются функции обратного вызова, вам надо привязать метод к тому объекту, на котором он будет вызываться, чтобы значение `this` было корректным. С React привязка метода к компоненту происходит автоматически ([кроме тех случаев, когда вы используете классы ES6](/react/docs/reusable-components.html#no-autobinding)). И делается это с минимальной нагрузкой на процессор и память.
**Делегирование событий:** На самом же деле, React добавялет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает кому из обработчиков его передать. Когда в памяти больше не остается обработчиков, они перестают работать. Если хотите узнать о том, почему такая механика так быстро работает, посмотрите [отличный пост в блоге David Walsh](http://davidwalsh.name/event-delegate).
**Делегирование событий:** На самом же деле, React добавляет обработчики событий не к узлам дерева. Сразу после запуска, React начинает прослушивать все события с самого верхнего уровня, используя единый слушатель. Когда добавляется новый компонент или удаляется старый, обработчики событий просто добавляются или удаляются из памяти React. И когда событие наступает, React уже заранее знает какому из обработчиков его передать. Когда в памяти больше не остается обработчиков, React перестает обрабатывать события. Если хотите узнать о том, почему эта механика так быстро работает, посмотрите [отличный пост в блоге David Walsh](http://davidwalsh.name/event-delegate).
## Компоненты как конечные автоматы
@ -54,25 +54,25 @@ React считает интерфейсы обыкновенными конеч
## Как работает состояние
Чтобы сообщить React о том, что данные изменились, вы вызываете метод `setState(data, callback)`. В этом методе происходит обновление состояния `this.state` новыми данными из `data`, и компонент отрисуется заново. После этого, вызывается функция `callback`. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.
Чтобы сообщить React о том, что данные изменились, вы вызываете метод `setState(data, callback)`. В этом методе происходит обновление состояния `this.state` новыми данными из `data`, и компонент отрисуется заново. После этого вызывается функция `callback`. Но вы редко будете ей пользоваться, ведь React сам обновляет интерфейс.
## В каких компонентах хранить состояние?
Большинство компонентов должны просто брать данные из `props` и отрисовывать их. Но иногда вам надо реагировать на действия пользователя, делать запросы на сервер или просто сделать что-то по таймеру. В таких случаях используйте состояние.
**Старайтесь делать компоненты без состояния.** Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, снижать сложность приложения, упрощая его понимание.
**Старайтесь делать компоненты без состояния.** Следуя этому правилу, вы будете выносить работу с состоянием с уровня представления в другие, более подходящие места. Тем самым, вы снизите сложность приложения, упрощая его понимание.
Основной принцип такой: создаются несколько компонентов без состояния, которые формируют дерево. Они будут заниматься только отрисовкой данных. А все данные для них будут у родительского компонента, который будет на вершине этого дерева компонентов. Он и будет передавать данные дочерним узлам через `props`. Этот компонент с общим состоянием содержит в себе всю логику взаимодействия, а дочерние компоненты будут только отрисовывать данные, которые будут у них в `props`.
## Какие данные *надо* помещать в состояние?
**Состояние должно содержать данные, которые нужны для обновления интерфейса.** В реальных приложениях такие данные крайне малы и передаются, обычно, через JSON-файлы. Когда создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода `render()` вычисляйте остальные данные, используя значения из состояния.
Со временем вы увидите, что написание приложений таким способом позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.
**Состояние должно содержать данные, которые нужны для обновления интерфейса.** В реальных приложениях такие данные, как правило, незначительны по объему, и могут быть сериализованы в JSON. Когда создаете компонент с состоянием, старайтесь поместить в него минимум данных. А уже внутри метода `render()` вычисляйте остальные данные, используя значения из состояния.
Со временем вы увидите, что такой подход позволяет создавать более стройные и устойчивые к изменениям приложения. Добавление в состояние лишних данных требует от вас дополнительных затрат на их синхронизацию. Но этого можно избежать, если позволить React делать все эти вычисления за вас.
## Какие данные *не надо* помещать в состояние?
Состояние `this.state` должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит ложить туда:
Состояние `this.state` должно содержать минимум данных, необходимых для отображения интерфейса. Поэтому не стоит хранить в нем:
* **Вычисляемые данные:**Вам не надо думать о тех данных, которые надо вычислять через данные состояния — лучше позаботьтесь об интерфейсе, а все вычисления делайте в методе `render()`. Например, если в состоянии хранится список элементов и вам надо вывести его размер в виде строки. Напишите `this.state.listItems.length + ' элементов'` в методе `render()`. Это будет правильнее, чем хранить размер списка в состоянии.
* **Компоненты React:** Создавайте их в методе `render()` опираясь на данные из `props` и `this.state`.
* **Значения, повторяющие `props`:**старайтесь использовать `props` только как источник данных для отрисовки. Хранить значения `props` в состоянии допускатеся, только если вам надо где-то хранить их прошлые значения, ведь `props` могут измениться после отрисовки родительского компонента.
* **Вычисляемые данные:**Не волнуйтесь о данных, которые можно вычислить из состояния. Согласованность данных проще обеспечить, если производить все вычисления в методе `render()`. Например, если в состоянии хранится список элементов и вам надо вывести его размер в виде строки, напишите `this.state.listItems.length + ' элементов'` в методе `render()`. Это будет правильнее, чем хранить размер списка в состоянии.
* **Компоненты React:** Создавайте их в методе `render()`, опираясь на данные из `props` и `state`.
* **Значения, повторяющие `props`:**Старайтесь по мере возможности использовать `props` как единственный источник данных. Хранить значения `props` в состоянии допускается, только если вам надо где-то хранить их прошлые значения, ведь `props` могут измениться после отрисовки родительского компонента.