Несколько лет назад мой друг Шон начал рассказывать мне, как эта новая интерфейсная библиотека под названием React собирается захватить власть в Интернете. Сначала я отклонил это как еще одну причуду фреймворка. Но потом я стал слышать о React все больше и больше, до такой степени, что мне казалось, что игнорировать его больше нельзя.

Может быть, вы находитесь в том же положении, что и я: вы слышали о React слева и справа, но на самом деле сидите и изучать это кажется такой рутинной работой.

Хорошая новость в том, что все, что вам нужно знать о React, можно свести к пяти ключевым концепциям.

Не поймите меня неправильно, это не значит, что я могу мгновенно превратить вас в мастера React. Но, по крайней мере, вы поймете все основные концепции, если решите вмешаться.

Пять ключевых концепций:

  1. Компоненты
  2. JSX
  3. Реквизит и состояние
  4. Component API
  5. Типы компонентов

Прежде чем мы начнем, обратите внимание, что я изначально изучал React на курсах Уэса Боса и добавил на них несколько партнерских ссылок. По возможности я также включал ссылки на бесплатные ресурсы.

О, а мой друг Шон? С тех пор он перешел к гораздо более передовым вещам. В конце концов, React так 2015.

Концепция # 1: Как работают компоненты React

Первое, что вам нужно знать о React, это то, что все дело в компонентах. Ваша кодовая база React - это просто одна большая куча больших компонентов, которые вызывают более мелкие компоненты.

Но что это за компонент, спросите вы? Прекрасным примером компонента является обычный HTML-элемент <select>. Он не только имеет собственный визуальный вывод (серое поле, текстовую метку и стрелку вниз, которые составляют сам элемент), но и обрабатывает свою собственную логику открытия и закрытия.

А теперь представьте, что вы можете создать свой собственный автономный пользовательский <select> со своим собственным стилем и поведением:

Что ж, это именно то, что позволяет вам делать React. Компонент React - это отдельный объект, который не только выводит HTML, как традиционный шаблон, но также включает весь код, необходимый для управления этим выводом.

На практике наиболее распространенный способ написания компонентов React - это использование класса ES6, содержащего render метод, возвращающий HTML. (Существует также суперсекретный функциональный способ, но вам придется подождать до концепции №4, чтобы узнать о нем):

class MyComponent extends React.Component {
  render() {
    return <p>Hello World!<p>;
  }
}

Концепция # 2: Как работает JSX

Как видите, компонентный подход означает, что код HTML и JavaScript находится в одном файле. Секретным оружием React для достижения этого нечестивого альянса является язык JSX (где X означает XML).

Поначалу JSX может показаться неудобным, но к нему быстро привыкаешь.

Да, я знаю. Нас всех учили четко разделять HTML и JavaScript. Но оказывается, что небольшое ослабление этих правил может творить чудеса с производительностью вашего интерфейса.

Например, поскольку теперь в вашем распоряжении все возможности JavaScript, вот как вы можете отобразить текущую дату, вставив фрагмент кода JavaScript в свой HTML-код с помощью {...}:

class MyComponent extends React.Component {
  render() {
    return <p>Today is: {new Date()}</p>;
  }
}

Это также означает, что вы будете использовать простой JavaScript для if операторов или циклов, а не какой-то специфичный для шаблона синтаксис. Тернарный оператор JavaScript здесь особенно удобен:

class MyComponent extends React.Component {
  render() {
    return <p>Hello {this.props.someVar ?  'World' : 'Kitty'}</p>;
  }
}

И, кстати, если вам нужно освежить в памяти новейшие аспекты синтаксиса JavaScript, я рекомендую ES6 for Every от Уэса Боса (если вам нравятся видео) или Practical ES6 от Nicolas Bevacqua (если вы предпочитаете читать).

Концепция # 3: как работают реквизиты и состояние

Может быть, вам интересно, откуда взялась указанная выше переменная this.props.someVar.

Если вы когда-либо писали строку HTML, вы, вероятно, знакомы с атрибутами HTML, такими как <a> тега href. В React атрибуты известны как реквизиты (сокращение от «свойства»). Реквизит - это то, как компоненты общаются друг с другом.

class ParentComponent extends React.Component {
  render() {
    return <ChildComponent message="Hello World"/>;
  }
}
class ChildComponent extends React.Component {
  render() {
    return <p>And then I said, “{this.props.message}”</p>;
  }
}

Из-за этого поток данных React является однонаправленным: данные могут передаваться только от родительских компонентов к их дочерним компонентам, а не наоборот.

Однако иногда компоненту необходимо реагировать на данные, которые не исходят от родительского компонента (например, на ввод данных пользователем). И здесь на помощь приходит состояние.

Хорошей метафорой для понимания разницы между реквизитом и состоянием будет Etch-A-Sketch. В отличие от таких вещей, как цвет корпуса и положение циферблата планшета Etch-A-Sketch (реквизиты), сам рисунок (состояние) не является неотъемлемым свойством Etch-A-Sketch. Эскиз. Это всего лишь временный результат действий пользователя.

Обратите внимание, что состояние компонента также может быть передано его собственным дочерним элементам как свойство. Вы можете представить себе это как большую реку, текущую под гору, с маршрутизатором, уровнем данных и различными компонентами, каждый из которых добавляет свой небольшой поток данных для формирования основного состояния приложения.

Внутри компонента состояние управляется с помощью функции setState, которая часто вызывается внутри обработчика событий:

class MyComponent extends React.Component {
  handleClick = (e) => {
    this.setState({clicked: true});
  }
  render() {
    return <a href="#" onClick={this.handleClick}>Click me</a>;
  }
}

На практике подавляющее большинство данных в приложении React будет опорой. Только когда вам нужно принять вводимые пользователем данные, вы можете использовать состояние для обработки изменений.

Обратите внимание, что здесь мы используем толстую стрелку, чтобы привязать обработчик handleClick. Вы можете узнать больше об этой технике здесь.

Концепция №4: Как работает компонентный API

Мы уже упоминали render и setState, которые являются частью небольшого набора методов компонентного API. Еще один полезный - constructor, который вы можете использовать для инициализации вашего состояния и методов привязки.

Помимо этих трех функций, React также предоставляет набор обратных вызовов, запускаемых в различных точках жизненного цикла компонента (перед загрузкой, после загрузки, после размонтирования и т. Д.). Если вы не занимаетесь продвинутым вуду React, вам, вероятно, почти никогда не придется об этом беспокоиться.

Если этот раздел кажется коротким, это связано с тем, что изучение React на самом деле гораздо больше касается освоения программирования и архитектурных концепций, а не изучения набора скучных методов API. Вот что делает его таким освежающим!

Концепция # 5: Как работают типы компонентов

Мы видели, как использовать классы для определения компонента:

class MyComponent extends React.Component {
  render() {
    return <p>Hello World!<p>;
  }
}

И мы также говорили о методах компонентов, поддерживаемых этими классами. А теперь забудьте о них! Все больше и больше людей пишут компоненты React как функциональные компоненты.

Функциональный компонент - это функция, которая принимает объект props в качестве аргумента и возвращает кучу HTML. Почти как традиционный шаблон, с той ключевой разницей, что вы все равно можете использовать любой код JavaScript, который вам нужен внутри этой функции:

const myComponent = props => {
  return <p>Hello {props.name}! Today is {new Date()}.</p>
}

Следствием использования синтаксиса функционального компонента является потеря доступа к методам компонента, о которых мы только что говорили. Но оказывается, что на практике это прекрасно, поскольку подавляющему большинству ваших компонентов они, вероятно, не понадобятся.

Между прочим, один из этих методов - setState, и это означает, что функциональные компоненты не могут иметь состояния. По этой причине их часто называют функциональными компонентами без сохранения состояния.

Поскольку функциональные компоненты требуют гораздо меньше шаблонного кода, имеет смысл использовать их, когда это возможно. По этой причине большинство приложений React содержат здоровое сочетание обоих синтаксисов.

Обратите внимание, что есть еще третий, устаревший синтаксис, использующий функцию createClass. Но любой, кто использует его, должен быть пристыжен и называть имена за то, что осмелился все еще использовать шаблоны кодирования 18 месяцев назад:

var Greeting = React.createClass({ 
  
  render: function() {     
    return <h1>Hello, {this.props.name}</h1>;   
  }
});

Концепция # 6: Как работают роли компонентов

Хорошо, я солгал. Фактически их шесть, а не пять. Но что я могу сказать, фильм не называется «Шесть пальцев смерти». Хотя сейчас, когда я думаю об этом, это звучит так, как будто это был бы довольно крутой фильм, вероятно, с участием какого-то инопланетного мастера кунг-фу, жаждущего мести.

Но вернемся к нашей теме. Теперь перейдем к скучным архитектурным решениям, о которых я говорил. Так что, если все это не имеет смысла, не стесняйтесь возвращаться, когда у вас будет возможность еще немного поиграть с React.

После некоторого использования React люди начали замечать, что в их компонентах появляются два разных «вида» кода: один из них был связан с логикой UI, такой как отображение и скрытие объекта. А другой был посвящен логике данных, например загрузке данных с вашего сервера.

Это привело к различию между контейнерными и презентационными компонентами (также иногда называемыми умными и глупыми. компоненты). Компоненты контейнера должны обрабатывать ваши данные, но - и это важная часть - не ваш пользовательский интерфейс. Компоненты представления - это прямо противоположное.

Другими словами, в классическом примере списка дел один компонент загружает данные, а затем передает эти данные другому компоненту, который будет отвечать за вывод фактической разметки HTML и обработку изменения местного состояния.

Это очень похоже на шаблон представления / контроллера, с которым вы, возможно, знакомы по временам внутреннего разработчика. (’участник Rails?’ участник Django?)

Различие между контейнером и презентацией было популяризировано в этой записи блога Дэна Абрамова (создателя Redux), и я рекомендую проверить это, если вы хотите копнуть глубже.

Компоненты высшего порядка

Прежде чем мы подведем итоги, мы должны немного поговорить о типе компонентов контейнера, известном как компоненты более высокого порядка (часто сокращаются как HoC).

HoC - это компонент, который вы можете обернуть вокруг другого компонента, чтобы передать ему специальные свойства, и обычно он создается с помощью функции фабрики компонентов более высокого порядка. Обратите внимание, что люди обычно называют саму функцию HoC, что может быть не на 100% технически правильным, но на практике не имеет большого значения.

Например, вызов withRouter фабричной функции React Router на <MyComponent> обернет ее в компонент new<withRouter(MyComponent)/>, который передает свойство Router вышеупомянутому <MyComponent>.

Вы можете представить себе функцию HoC как тележку для гольфа, которая следует за игроком в гольф и передает ему нужную клюшку. Сами по себе кэдди на самом деле ничего не делать с клюшками для гольфа. Они нужны только для того, чтобы дать игроку в гольф доступ к большему количеству инструментов.

HoC - очень мощная концепция. Например, библиотека Recompose даже позволяет обрабатывать изменения состояния через HoC. Другими словами, теперь вы можете управлять состоянием, не задействуя какие-либо компоненты на основе классов ES6.

Поскольку композиция HoC становится настолько распространенной, кажется, что React может отойти от синтаксиса класса ES6 и перейти к чисто функциональному подходу. Интересные времена!

Резюме

Итак, давайте резюмируем то, что мы только что узнали:

  • Кодовая база React состоит из компонентов.
  • Эти компоненты написаны с использованием JSX.
  • Данные передаются от родителя к потомкам, за исключением случая state, который возникает внутри компонента.
  • Компоненты обладают небольшим набором методов жизненного цикла и утилит.
  • Компоненты также могут быть записаны как чистые функции.
  • Вы должны хранить логику данных и логику пользовательского интерфейса в отдельных компонентах.
  • Компоненты более высокого порядка являются обычным шаблоном для предоставления компоненту доступа к новым инструментам.

Хотите верьте, хотите нет, но мы только что охватили 90% знаний, которые каждый день использует React-разработчик. Независимо от того, насколько абстрактным или непонятным является шаблон, все в React всегда можно свести к функциям и реквизитам.

Как только вы это поймете по-настоящему, React перестанет пугать. Вы сможете увидеть закономерности в коде, сразу понять новые кодовые базы, и только тогда вы сможете с гордостью заявить:

«Пффф! React - это так 2015! »

Идти дальше

Если мне удалось убедить вас, что React не так уж плох, вы можете попробовать изучить его как следует. Если да, то я не могу порекомендовать видеокурс React для начинающих. Именно так я сам изучил React, и на самом деле он был обновлен, чтобы охватить все интересные новые вещи, такие как функциональные компоненты без сохранения состояния:

Если вы не хотите, чтобы ваши кровно заработанные доллары шли на финансирование гнусного лобби React (я слышал, что Дэн Абрамов находится на своей третьей яхте), вы также можете бесплатно изучить этот огромный список ресурсов React.

А если вам нужно применить все эти недавно приобретенные знания на практике, внося свой вклад в крутой проект с открытым исходным кодом React, посмотрите Telescope Nova. Это самый простой способ быстро создать полнофункциональное приложение React + GraphQL с учетными записями пользователей, формами и загрузкой данных прямо из коробки. Я уже упоминал, что мы ищем участников?

Наконец, если вам понравилась эта статья, поделитесь ею и порекомендуйте ее (это маленькое зеленое сердечко чуть ниже). И, пожалуйста, дайте мне знать в Твиттере, о чем вы хотите, чтобы я написал дальше!