Статьи

На освоєння React мені потрібна була всього тиждень, а чим ви гірші? - CSS-LIVE

  1. чесне попередження
  2. Руйнівники легенд: спецвипуск про практичність в реактив
  3. Міф # 1: для реактив необхідно використовувати вбудовані стилі.
  4. Міф # 2: для атрибутів елемента доведеться використовувати JavaScript-синтаксис, який зовсім не схожий на HTML.
  5. Міф # 3: щоб випробувати реактив, потрібне розуміння всіх інструментів для збірки.
  6. Використання реактив в типових додатках
  7. Використання реактив в CodePen
  8. Використання реактив
  9. Звичайні підозрювані: змінні і обробка подій
  10. Об'єднання реактив з іншими бібліотеками (в даному випадку Greensock)
  11. Створення глобальної функції-хелпери
  12. Ця справа: управління станом
  13. Для цієї частини розберемо пару речей, дуже важливих для розуміння того, як звертатися і працювати...
  14. Props на практиці
  15. Практика
  16. Важлива частина цього, яку потрібно враховувати - потрібно функція handleChange
  17. Основні поняття стану
  18. Ref-и
  19. Keys і використання Ref-ів
  20. А тепер все разом
  21. Висновок

Переклад статті I Learned How to be Productive in React in a Week and You Can , Too з сайту css-tricks.com для css-live.ru . Автор - Сара Дреснер .

Ця стаття предназнаена не для бувалих React-профі , А скоріше для тих, хто заробляє розробкою сайтів і кому цікаво, що реактив може нам підказати щодо осучаснення призначених для користувача інтерфейсів. React вже давно займає мене, і оскільки тепер він завоював певне положення і хороші відгуки в співтоваристві, не шкода витратити час на його вивчення. У фронтенд-розробці постійно з'являється так багато нових технологій, що часом навіть важко зрозуміти, чи варто витрачати сили на їх вивчення. У цій статті я збираюся розглянути найцінніші на мій погляд, практичні міркування, щоб ви змогли почати працювати з React.

чесне попередження

На роботу з цим матеріалом я витратила всього тиждень. Навмисно. Я пишу це, поки ця технологія мені ще в новинку, і можу писати про неї, виходячи з цього. У цьому стані я набагато краще запам'ятовую місця, на яких я спотикалася і знахідки на цьому шляху.

Я користувалася курсом «React для початківців» Ваги Боса, а також «Введенням в React.js для тих, чий рівень знання jQuery достатній, щоб впоратися з React» . Я дуже рекомендую ці ресурси.

Минуло два дні:

See the Pen Baby's First React Attempt by Максим ( @psywalker ) on CodePen .

Поки далеко від ідеалу, але навряд чи я сама просунулася б ще далі за цей проміжок часу.

Якщо ви з тих, хто бажає відразу ж зануритися в реактив і повністю вивчити його, включаючи складання та необхідний інструментарій - це приголомшливо! Почніть з цього . А ще я б порадила цей чудовий курс від «Frontend Masters»: «Сучасні веб-додатки»

Руйнівники легенд: спецвипуск про практичність в реактив

Поки ми не почали, мені б хотілося розвіяти пару основних міфів, які, на мій погляд, є перепонами для більшості людей.

Міф # 1: для реактив необхідно використовувати вбудовані стилі.

Неа! Ні в якому разі. Можна використовувати CSS, як і зазвичай. Витративши багато часу на рефакторинг гігантського обсягу CSS-коду, я зрозуміла, наскільки це важливо. Реактив відносно новий і йому поки не доводилося витримувати випробування переробками дизайнів. Якби мені довелося заново продиратися через тисячі рядків вбудованих стилів заради поновлення padding і line-height, мене б, як розробника, це напевно засмутило.

Проте бувають випадки, коли вбудовані стилі доцільні. Якщо є компонент, який змінює стилі в залежності від їх стану (наприклад: візуалізація даних), то вбудовані стилі виявилися б вельми до речі, щоб не довелося підтримувати нереальне число статичних стилів (у багатьох місцях), обробляючи всілякі стану.

Хоча мені здається, це могло б бути на додачу до базового CSS, використовуваному додатком, і було б швидше винятком, ніж правилом. Однак, в інтернеті всім вистачить місця, так що ніщо не абсолютно.

Міф # 2: для атрибутів елемента доведеться використовувати JavaScript-синтаксис, який зовсім не схожий на HTML.

Ще одна, на мій погляд, приємна деталь в стилі викладання Веса Боса, це те, як він поступово підводить слухача до більш звичного підходу і реалізації. Я іноді грішу надмірно спрощеним і очевидним кодом, хоча і розумію, що іншим подобаються приклади поабстрактнее.

Він пропонує писати розмітку за допомогою JSX , Який найбільш близький до нашого друга, традиційному HTML, так що особисто для мене це набагато зрозуміліше. Тому замість:

return React.createElement ( "p", {className: "foo"}, "Привіт, світ!");

Ми писали б:

return (<p className = "foo"> Привіт, світ! </ p>);

Кожен з них працює. Але коли наша розмітка стає все складніше, я виявила, що знайомий HTML у вигляді JSX допомагає моєму розумінню. Але врахуйте, що навіть з JSX є незначні відмінності.

Міф # 3: щоб випробувати реактив, потрібне розуміння всіх інструментів для збірки.

І дійсно, для реактив потрібно використовувати інструменти для збірки, тому, як правило, туторіали починаються з цього. Але я б порадила починати з того, що якщо ви зовсім новачок, вам слід було б поколупатися на CodePen , JSBin або JSFiddle . Це - хороший спосіб повторювати і засвоювати уроки, перш ніж вкладати купу сил в абсолютно нову технологію. З метою зробити перший крок, в сьогоднішніх прикладах я планую використовувати CodePen.

Використання реактив в типових додатках

У типових додатках на React 0.14+ насамперед нам потрібно React і ReactDOM:

var React = require ( 'react'); var ReactDOM = require ( 'react-dom');

А потім виклик ReactDOM.render:

ReactDOM.render (routes, document.querySelector ( '# main'));

Використання реактив в CodePen

У нашому випадку просто виберемо реактив з меню, що випадає в панелі JS (клацніть на іконку шестерінки вгорі панелі), а потім скористаємося Babel в якості компілятора.

Нам не потрібно підключати React або ReactDOM за допомогою require, оскільки у нас немає ніякої маршрутизації, а ми використовуємо компонент додатка безпосередньо. Просто підправимо наш код:

React.render (<App />, document.querySelector ( "# main")); <Div id = "main"> </ div>

Також, щоб приступити до роботи, потрібно відладчик для реактив у вигляді розширення для Chrome або для Firefox , Які відмінно підходять для налагодження віртуальної DOM.

У разі CodePen можете вибрати «Налагоджувальний режим» , І це розширення автоматично визначить реактив:

У разі CodePen можете вибрати   «Налагоджувальний режим»   , І це розширення автоматично визначить реактив:

Використання реактив

Ось основні «цеглинки», які нам потрібно знати для подальшої роботи:

// Додаток var App = React.createClass ({render: function () {return (<div className = "foo"> Привіт, світ! </ Div>)}}); React.render (<App />, document.querySelector ( "# main"));

Розберемо це по частинах. В останньому рядку ми знаходимо id головного div (main) і відображаємо в ньому компонент <App />, що завантажує весь додаток реактив. Щоб побачити створений DOM-елемент, можна скористатися вкладкою «Реактив» в отладчике.

Ми прив'язали <App /> в якості першого компонента. По-перше, зверніть увагу, що цей тег пишеться з великої літери - хоча це і не обов'язково, але це вважається хорошим тоном в роботі з реактив-компонентами. По-друге, цей тег зачиняються самостійно. Теги в реактив повинні бути закриті, або додатковим закриває тегом (напр. </ Div>), або зачинятися (напр. <Hr> перетворився б в <hr />). Так працює JSX, інакше вискочить помилка.

Зверніть увагу на структуру для створення компонента додатка, що знаходиться вгорі. Рухаючись вперед, ви звикнете до цього синтаксису, оскільки все, що ми побудуємо сьогодні, буде працювати на основі цих блоків.

І останнє, що варто відзначити, це те, що замість класу для елемента ми використовуємо className. Це підступ, якщо ви звикли писати HTML-розмітку для веб-сторінок. На щастя, це легко виправити. В цієї документації відмінно описаний JSX і його синтаксис.

// Додаток var App = React.createClass ({render: function () {return (<Header />)}}); // Шапка var Header = React.createClass ({render: function () {return (<div className = "foo"> Привіт, світ! </ Div>)}}); React.render (<App />, document.querySelector ( "# main"));

Наступним кроком буде розширення програми за допомогою компонента. Назва для заголовка можна вибирати на свій смак, але для наочності, нехай воно відображає його роль в документі. Можна помітити, що якщо нам також знадобитися додати елемент навігації, зробити це не важко. Ось така ж сторінка зі стандартним бутстраповскім рядом кнопок для компонента <Nav />, і більш семантично h1 для нашого «Привіт, світ!» Замість div:

// Додаток var App = React.createClass ({render: function () {return (<div> <Nav /> <Header /> </ div>)}}); // Навігація var Nav = React.createClass ({render: function () {return (<ul className = "nav nav-pills"> <li role = "presentation" className = "active"> Головна </ li> <li role = "presentation"> Профіль </ li> <li role = "presentation"> Повідомлення </ li> </ ul>)}}); // Шапка var Header = React.createClass ({render: function () {return (<h1 className = "foo"> Привіт, світ! </ H1>)}}); React.render (<App />, document.querySelector ( "# main"));

Нічого складного, правда? Все одно, що будівельні блоки будь-який веб-сторінки. Ми створили навігацію з шапкою, і застосували ці компоненти до компоненту додатка, який відображений в body. Єдиним секретом останнього прикладу може здатися незрозумілий додатковий div навколо <Header /> і <Nav />. Це тому, що ми повинні завжди повертати один елемент. У нас не може бути два сестринських елемента, ось і доводиться обертати їх в один div.

Тепер, розібравшись зі Будівельної блоками, ви повинні без проблем зібрати цілу сторінку за допомогою реактив і його компонентів. Я б порадила зробити рефакторинг макета вже створеної вами сторінки, просто заради навчання. Додайте туди таблицю стилів і збирайте крок за крок інші деталі, поки не відновляться її повністю. Для практики саме те.

Можна, можливо автоматизувати цей процес , Але я б не радила використовувати подібний інструмент до тих пір, поки ви спочатку не пройдете всі етапи налаштування оточення під себе. Тому, зіткнувшись надалі з проблемами, зрозуміти те, що відбувається не складе труднощів.

Звичайні підозрювані: змінні і обробка подій

Давайте додамо трохи обробки подій і простих змінних, для початку просто щоб зрозуміти, як це відбувається.

І знову візьмемо перше демо (давайте використовувати його протягом всієї статті):

У компонента статті в блозі досить проста розмітка, так що почнемо з цього:

// Стаття в блозі var Post = React.createClass ({render: function () {return (<div className = "blog-post"> <h3 className = "ptitle"> {this.props.ptitle} <small> { this.props.date} </ small> </ h3> <img className = "thumbnail" src = {this.props.pimg} /> <p> {this.props.postbody} </ p> <div className = "callout callout-post"> <ul className = "menu simple"> <li> Author: {this.props.author} </ li> <li> Comments: {this.props.comments} </ li> <li > Tags: {h.getTaggedName ()} </ li> </ ul> </ div> </ div>)}});

Додамо довільну змінну і обробник події і подивимося, як це працює. Перше, що варто врахувати - якщо ми використовуємо JSX, то фігурні дужки повідомлять реактив, що ми готові використовувати JavaScript. Так що наша змінна буде виглядати як {var}.

Ми хочемо додати оператор змінної всередину виклику функції render, але перш, ніж повернути розмітку. Можна потім отримати до неї доступ, викликавши змінну, в даному випадку {com}. Подія по кліку - вбудований обробник onClick, ймовірно, такий, що суперечить хорошому тону, до якого ви звикли. Це ім'я ми вибрали самі, коли як render - метод фреймворка. Ми викликали {this.tryClick} і пишемо метод, що зберігається як tryClick (довільне ім'я) всередині того ж компонента, наприклад:

// Стаття в блозі var Post = React.createClass ({tryClick: function () {alert ( 'просто випробувати події при натисканні лалала');}, render: function () {var com = "Comments"; return (<div className = "blog-post"> <h3 className = "ptitle"> {this.props.ptitle} <small> {this.props.date} </ small> </ h3> <img className = "thumbnail" src = {this.props.pimg} /> <p> {this.props.postbody} </ p> <div className = "callout callout-post"> <ul className = "menu simple"> <li> <a href = "#" onClick = {this.tryClick}> Author: {this.props.author} </a> </ li> <li> {com}: {this.props.comments} </ li> <li> Tags : {h.getTaggedName ()} </ li> </ ul> </ div> </ div>)}});

Синтаксис для подій в реактив починається з «on» і використовує верблюжійРегістр. наприклад:

  • click = onClick
  • mouseEnter = onMouseEnter
  • keyPress = onKeyPress

Тут можна знайти повний список всіх підтримуваних подій.

Об'єднання реактив з іншими бібліотеками (в даному випадку Greensock)

Для анімації я вважаю за краще GSAP . У реактив можна використовувати і інші бібліотеки, тому Об'єднаємо GSAP з реактив і подивимося, що буде.

Ми хочемо звертатися до інших бібліотек в потрібний момент, тому потрібно переконатися, що вони викликаються відразу ж після першого методу render. І в цьому нам допоможе метод componentDidMount. Ще трохи про інші методи життєвого циклу ми поговоримо пізніше, але поки для нас важливо те, що цей метод викликається відразу ж після вставки компонента в документ.

Якщо ви звикли до jQuery, то напевно знайомі з вибіркою елементів прямо з DOM. В цьому випадку, навіть при анімації DOM-елементів ми скористаємося методом getDOMNode () реактив, а не просто виберемо їх. А також ви помітите, що насправді ми викликаємо функцію для анімації в компоненті програми, і просто передаємо її нижче нашим боксів. (Щоб побачити анімацію, можливо доведеться натиснути кнопку «Rerun»)

// Додаток var App = React.createClass ({componentDidMount: function () {var sq1 = this.refs.first.getDOMNode (); var sq2 = this.refs.second.getDOMNode (); var sq3 = this.refs. third.getDOMNode (); var sq4 = this.refs.fourth.getDOMNode (); var sq5 = this.refs.fifth.getDOMNode (); var allSq = [sq1, sq2, sq3, sq4, sq5]; TweenLite.set (allSq, {css: {transformPerspective: 400, perspective: 400, transformStyle: "preserve-3d"}}); TweenMax.to (sq1, 2.5, {css: {rotationX: 230, z: -600}, ease: Power2.easeOut}, "+ = 0.2"); TweenMax.to (sq2, 2.5, {css: {rotationY: 230, z: -150}, ease: Power4.easeOut}, "+ = 0.2"); TweenMax. to (sq3, 2.5, {css: {rotationX: 500, z: 150}, ease: Power2.easeInOut}, "+ = 0.2"); TweenMax.to (sq4, 2.5, {css: {rotationY: 500, z : -150}, ease: Power4.easeOut}, "+ = 0.2"); TweenMax.to (sq5, 2.5, {css: {rotationX 1000, z: 100}, ease: Power2.easeOut}, "+ = 0.2 ");}, render: function () {return (<div className =" scene "> <Box ref =" first "> </ Box> <Box ref =" second "> </ Box> <Box ref = "third"> </ Box> <Box ref = "fourth"> < / Box> <Box ref = "fifth"> </ Box> </ div>)}}); // Box var Box = React.createClass ({render: function () {return (<div className = "squares"> </ div>)}}); React.render (<App />, document.querySelector ( "# main"));

Можливо, ви звикли звертатися до DOM через jQuery або ванільний JavaScript. Можна як і раніше робити так, але тут ми звертаємося до частин DOM через getDOMNode () і refs, в цьому рядку: var sq1 = this.refs.squares1.getDOMNode () ;. Трохи докладніше про це написано в документаціїї реактив .

У реактив є й інші способи додати динаміки вашим проектам - React-Motion Ченга Лу просто чудовий, ще варто відзначити React-GSAP-Enhancer .

Створення глобальної функції-хелпери

Можна навіть писати функції-хелпери, до яких легко може звертатися безліч компонентів. Для цих функцій підходить та ж точкова нотація, що і для this.functionName. Ми зберігаємо функцію-хелперів (в цьому прикладі на CodePen - прямо на початку файлу, але в реальних додатках це був би окремий файл) і оголошуємо кожну з них в якості об'єкта, таким же способом, як і в структурі компонента.

Щось на зразок правильно відформатованої дати в першому демо зі статтями блоку могло б виглядати так:

var h = {getTime: function () {var month = [ "jan", "feb", "march"]; // .... and so on var d = new Date (); var mon = month [d.getMonth ()]; var day = d.getDate (); var year = d.getFullYear (); var dateAll = mon + "" + day + "," + year; return dateAll; }};

І використано ось так: {h.getTime ()}

Ця справа: управління станом

Добре! Тепер, коли ми розібралися з будівельними блоками, перейдемо до однієї з найбільш класссная речей.

Реактив безумовно гарний у створенні простих для розуміння і невеликих розмірів компонентів, але де дійсно проявляється його міць - це управління станом для цих компонентів. Розберемо це трохи докладніше.

Для цієї частини розберемо пару речей, дуже важливих для розуміння того, як звертатися і працювати з елементами, які змінюються.

  1. Перше - це стан. Воно - приналежність компонента, а значить, його область видимості обмежена компонентом, і ми будемо звертатися до нього так: {this.state.foo}. Можна оновити стан, викликавши this.setState ().
  2. Друге стосується того, як передавати (призначені тільки для читання) дані від батька до компоненту (на кшталт того, як додаток було батьком для header в першому прикладі). Ми кличемо це props, як в слові «property» (властивість), і будемо використовувати його прямо в компоненті за допомогою {this.props.foo}. Дочірні елементи компонента не можуть змінювати ці дані.

Кожен раз, коли ми міняємо щось із цих двох речей і наш компонент залежить від цього, реактив буде перемальовувати ті частини вашого компонента, які йому знадобиться

Принадність віртуальної DOM в тому, що реактив шукає тільки ті Ноди в DOM, які потрібно оновити.

Тепер я прочитала купу всього про стан, але думаю, була вага вдалося висловитися ясніше всіх, тому я перефразую його: Якщо ви звикли до jQuery, то всі дані у вас зберігаються в DOM. Реактив це ні до чого, він зберігає дані в об'єкті (стані), а потім отрісовиваєт речі, в залежності від об'єкта. Це як головний еталон, від якого все залежить.

Props на практиці

Для початку давайте просто випробуємо this.props, додавши {this.props.title} до компоненту Header, а після звернемося до нього в додатку.

// Додаток var App = React.createClass ({render: function () {return (<Header greeting = "Hello, world!" />)}}); // Шапка var Header = React.createClass ({render: function () {return (<div className = "foo"> <h1> {this.props.greeting} </ h1> </ div>)}}); React.render (<App />, document.querySelector ( "# main"));

Для props можна також додати значення за замовчуванням, в методі життєвого циклу з дуже підходящою назвою getDefaultProps. Це здорово, оскільки іноді не хочеться вказувати props для кожного компонента. Прикладом може бути аватар за замовчуванням, поки користувач не вибрав собі справжній, як яйце в Твіттері, або установка списку в якості порожнього масиву, який буде наповнений пізніше.

var ProfilePic = React.createClass ({getDefaultProps: function () {return {value: 'twitter-egg.jpg'}; ...});

Практика

Давайте трохи розвинемо це і попрацюємо з станами. Якщо ми в підсумку маємо наміру змінювати this.state, потрібно довести його до готовності. Для цього скористаємося getInitialState, що дозволить встановити, який стан найперше. Без цього ми не зможемо додати стан.

Давайте просто міняти фон в залежності від вибору користувача.

// Додаток var App = React.createClass ({/ * Встановити свой статус * / getInitialState: function () {return {bgColor: "teal"};} / * змінює стан * / handleColorChange: function (color) {// коли стан встановлюється безпосередно, // реактив НЕ знає про це, вісь чому ми вікорістовуємо setState this.setState ({bgColor: color});} / * для методів життєвого циклу * / updateBackgroundColor: function () {var body = document.querySelector ( 'body') body.style.background = this.state.bgColor} / * методи життєвого циклу * / componentDidMount: function () {this.updateBackgroundColor ()}, componentDidUpdate: function () {this.updateBackgroundColor ()}, render : function () {return (/ * віклікавші заголовок тут в компоненті, можна звертатися до this.props в шапці * / <div className = "foo"> <H1> Hello, World! &lt;/ H1> <label> What color? <ColorPicker value = {this.state.bgColor} onColorChange = {this.handleColorChange} /> </ label> </ div>)}}); // компонент ColorPicker var ColorPicker = React.createClass ({propTypes: {value: React.PropTypes.string.isRequired, onColorChange: React.PropTypes.func}, handleChange: function (e) {e.preventDefault (); var color = e.target.value // если того, хто нас (ColorPicker) відобразіть, захочеться дізнатіся, // коли змінівся колір, дайте Йому знаті if (this.props.onColorChange) this.props.onColorChange (color);}, render: function () {return (<select value = {this.props.value} onChange = {this.handleChange}> <option value = "orangered"> orangered </ option> <option value = "teal"> teal </ option > <option value = "orange"> orange </ option> <option value = "indigo"> indigo </ option> <option value = "red"> red </ option> </ select>)}}); React.render (<App />, document.querySelector ( '# main'));

Важлива частина цього, яку потрібно враховувати - потрібно функція handleChange

З нативними select-ами в звичайному DOM нічого подібного б не знадобилося, оскільки вони автоматично оновлювалися б за вибором користувачів. У реактив їхні капітали управляються компонентом, тому якщо потрібно, щоб input або select стежив за змінами, вам доведеться описати це в коді. Це означає, що за стан відповідає компонент, а не користувач.

На перший погляд незрозуміло, заради чого було стільки возитися, але ми навмисно залишаємо ці приклади маленькими. По-справжньому реактив проявляє себе, коли справа доходить до великих складнощів. Як би я не любила jQuery (а я до сих пір люблю jQuery, це не те, що можна висловити булевої змінної true / false), вам не вдасться піти від досить частою перевірки при змінах. У реактив це вирішується тим, що ця необхідність усувається завдяки простоті напрямку потоку даних, з цієї ж причини його простіше відслідковувати в дуже складних додатках.

Основні поняття стану

Тепер, коли ми розібралися в самих основах, давайте швиденько розглянемо, чому ми робимо саме так, і деякі передові методи.

Реактив показує кращі результати роботи, коли ми оновлюємо стану і перемальовували низькорівневі компоненти. По суті ми хочемо, щоб ці компоненти залишалися без стану і брали дані з високорівневих компонентів. Компоненти на верхніх рівнях ієрархії (на кшталт нашого застосування) працюють відмінно саме тоді, коли запам'ятовують стану. Таким чином вони управляють здебільшого логіки взаємодії і передають стан вниз за допомогою props. Проте, моменти, при яких у кожного компонента буде власний стан, не виключені. Однак, важливо пам'ятати, що сусідні компоненти повинні «спілкуватися» не безпосередньо, а через батьківський компонент.

Однак, важливо пам'ятати, що сусідні компоненти повинні «спілкуватися» не безпосередньо, а через батьківський компонент

Тому нам потрібно по максимуму зберігати стан в компоненті. Насправді, вам не варто турбуватися про те, коли щось перемальовується. Все, що вам важливо враховувати - коли змінюється стан, а про відображення реактив подбає сам.

З такої ідеології розробки безпосередньо випливає те, чому я також не раджу використання props в getInitialState, і тут можна докладніше почитати про те, чому це вважається антипаттерн .

Ми не хочемо занадто зловживати станом. Хоча компонент і відображається досить швидко, продуктивність може впасти, якщо дуже вже захопитися управлінням станом. Можна, можливо обійти це , Ледь це стане проблемою, але краще не потрапляти в такі ситуації, в принципі.

У решти статті ми обговоримо, як найкраще управляти цими станами і зберігати те, що не змінюється, на верхніх рівнях ієрархії, посилаючись при цьому на позбавлені стану компоненти нижче.

Ref-и

Інформацію про елемент можна також отримати за допомогою так званого ref. Використання Ref-ів здійснюється за рахунок прикріплення їх до будь-якого компонента. Потім вони повертаються під час виклику методу render () і після ми можемо посилатися на них зовні render (). Це вкрай корисно.

І знову візьмемо перший приклад на CodePen . Давайте на хвилинку замислимося, як створюються ці нові статті в блозі, і при цьому застосуємо ref-и.

На кожному полі форми у нас є ref, на зразок такого:

<Input type = "text" ref = "name" placeholder = "Full Name required" required />

А на самому елементі форми ми викликаємо:

onSubmit = {this.createPost}

який посилається на функцію createPost вище функції render, і використовує ref-и для зберігання інформації з відправляється форми:

var post = {name: this.refs.name.value, ...}

а потім можна звернутися до нього в стані додатки за допомогою this.props:

this.props.addPost (post);

addPost (post);

Це вкрай зручно, оскільки тепер є змінна post, з об'єктом, який зберігає свою назву (показано тут), дату, деталі і т.д. Ми як і раніше не зберігаємо нічого з цього в стані додатки, а тільки лише дали додатку можливість це використовувати. Розглянемо це докладніше в наступному розділі, заодно з keys.

Цей приклад я взяла в якості способу поговорити про ref-ах в цілому, але в додатках з реального життя, вам, можливо, захочеться розглянути щось на кшталт form-serialize , Щоб упакувати поля форми для відправки Аяксом.

Keys і використання Ref-ів

В останньому розділі ми створили спосіб зберігати дані, зібрані в формі, без передачі їх куди-небудь. Це тому, що в реактив ми прагнемо керувати цим станом у верхньому рівні ієрархії. Для збереження цього стану, ми запускаємо початковий стан з порожнім об'єктом. Ось де в результаті зберігаються дані з форми.

getInitialState: function () {return {posts: {}}},

Потім візьмемо функцію addPost. Зауважте, що управління перебуває тут, а не в формі, навіть хоча виклик відбувається з форми. Ми даємо станом Тимчасові місця, щоб статті залишалися унікальними, а також налаштовуємо стан для статей.

addPost: function (post) {var timestamp = (new Date ()). getTime (); // оновлення об'єкта стану this.state.posts [ 'post-' + timestamp] = post; // встановити свій статус this.setState ({posts: this.state.posts}); },

У кожного дочірнього елемента в масиві повинен бути унікальний key.prop. Це важливо, оскільки при першій-ліпшій можливості реактив все одно буде повторно використовувати існуючий DOM. Реактив використовує keys для відстеження того, які елементи в DOM він повинен оновити. Він позбавляє нас від перемальовування всіх DOM-елементів, коли це потрібно. Це покращує продуктивність нашого застосування.

Тепер давайте знову звернемося до додатка, і подивимося, що ми робимо з тільки що збереженими даними з форми:

// Додаток var App = React.createClass ({getInitialState: function () {return {posts: {}}}, addPost: function (post) {var timestamp = (new Date ()). GetTime (); // оновлення об'єкта стану this.state.posts [ 'post-' + timestamp] = post; // встановити свій статус this.setState ({posts: this.state.posts});}, renderPost: function (key) {return <NewPost key = {key} index = {key} details = {this.state.posts [key]} />}, render: function () {... return (<div> <Banner /> ... <div className = "list-of-posts"> {Object.keys (this.state.posts) .map (this.renderPost)} </ div> <Submissions addPost = {this.addPost} /> </ div> </ div> )}});

Можна бачити, що коли додаток відображається, ми використовуємо Object.keys для створення нового масиву. Потім беремо .map () з функцією renderPost, яку створимо заздалегідь. Для тих, хто не знайомий з .map (), вона корисна для створення масиву з існуючого масиву, можете уявити її у вигляді циклу.

<Div className = "list-of-posts"> {Object.keys (this.state.posts) .map (this.renderPost)} </ div>

Тепер давайте створимо цю саму функцію renderPost, яку тільки що викликали. Ми передаємо ключ в якості параметра і призначаємо його в якості ключа, індексу, і створюємо об'єкт, який ми називаємо details, щоб зберігати інформацію про стан статті.

renderPost: function (key) {return <NewPost key = {key} index = {key} details = {this.state.posts [key]} />},

Може здатися дивним, що ми передаємо key і index, але всередині компонента неможливо звернутися до ключу prop, тому ми передаємо ще один ключ під назвою index. Функція renderPost просто створює компонент <NewPost /> для кожного елемента в масиві, з подробицями, переданими вниз по ієрархії, до яких потім можна звернутися. Це досить-таки круто, оскільки, якщо в нашому стані щось оновиться, це пошириться вниз по ієрархії і ми зможемо керувати ним в одному місці.

У компоненті <NewPost /> зберігаються подробиці, винесені вниз по ієрархії для відображення всієї інформації. А створена нами раніше функція-хелперів, потрібна для правильно відформатованої дати, виглядає тут так: {h.getTime ()}:

/ * Нова стаття <NewPost /> * / var NewPost = React.createClass ({render: function () {var details = this.props.details; return (<div className = "blog-post"> <h3 className = " ptitle "> {details.title} <small> {h.getTime ()} </ small> </ h3> <img className =" thumbnail "src = {details.image} alt = {details.name} /> < p> {details.desc} </ p> <div className = "callout callout-post"> <ul className = "menu simple"> <li> Author: {details.name} </ li> <li> Comments: 0 </ li> <li> Tags: {h.getFunName ()} </ li> </ ul> </ div> </ div>)}});

getFunName ()} </ li> </ ul> </ div> </ div>)}});

А тепер все разом

Тепер, коли з keys все ясно, поглянемо на хвилинку на загальну картину. Ми розглянули getInitialState, componentDidMount і render, але в реактив є ще один метод при підключенні - componentWillMount. Він схожий на componentDidMount, але виконується прямо перед першим відображенням компонента.

Ця схема, звичайно, включає не всі можливості реактив, а лише коротку вижимки з пройденого нами матеріалу, і її цілком вистачить, щоб почати возитися з ним.

Висновок

Про реактив написано набагато більше, а ця стаття лише початок. Сподіваюся, це подорож новачка дозволило зрозуміти, як підготуватися до роботи з реактив. Ця стаття розтягнулася аж на 20 сторінок, але при цьому ми навіть не торкнулися масу інших важливих тем в зв'язку з реактив, що включають ES6, Browserify, Gulp, Webpack, незліченне число альтернативних реалізацій і багато іншого.

Знову ж таки, для подальшого вивчення, я настійно рекомендую зануритися в курс Веса Боса , І він пропонує 10% -знижку для читачів CSS-Tricks з кодом CSSTRICKS, а також подивитися деякі відео на Frontend Masters . У Майкла Джексона є прекрасний навчальний курс , На якому можна зареєструватися для участі (ми чекаємо його на Trulia в Сан-Франциско в березні!). Є також відмінний підручник Артемія Федосєєва під назвою «Основи реактив» и цей список Артема Сапегіна, який варто занести в закладки. Ну і не забувайте, що документація по реактив теж дуже непогана. Щасливого вивчення!

Дуже дякую Майклу Джексону , вазі Босу и Вел Хед за перевірку цієї статті.

PS Це теж може бути цікаво:

Lt;/ H1> <label> What color?

Новости