Начало работы с библиотекой React Javascript
Опубликовано: 2022-02-16Если вы проводите какое-то время в мире WordPress, вы, вероятно, сталкивались с Заком Гордоном. Зак — увлеченный и очаровательный преподаватель, специализирующийся на Javascript в WordPress. Он позаимствовал фразу «Углубленно изучайте Javascript» у Мэтта Малленвега и превратил ее в свой личный слоган.
В течение последних нескольких лет Зак выпускал видеоуроки, онлайн-конференции, живые выступления и подкасты, посвященные обучению вас использованию Javascript в WordPress.
Я рад сообщить, что мы работаем с Заком над книгой «Объяснение реакции». React — это библиотека, которую команда WordPress выбрала для нового редактора Gutenberg. Они не одиноки — и Drupal, и Magento также выбрали React.
Зак пишет в прямом эфире о своем писательском прогрессе на @zgordon в Твиттере. Вы также можете услышать, как Зак рассказывает о React в подкасте OSTraining.
В этом отрывке из книги Зак дает вам общий обзор React и некоторых ключевых концепций.
Что такое Реакт?
Из коробки React — это библиотека для создания пользовательских интерфейсов.
Хотя React является библиотекой JavaScript, интерфейсы, которые создает React, не зависят от него.
Существует несколько сопутствующих библиотек React, чтобы созданные вами интерфейсы работали в браузере, на сервере, в нативных приложениях и даже в средах 360 и VR. В этой книге мы сосредоточимся на работе с ReactDOM, библиотекой, которая управляет добавлением интерфейсов, которые мы создаем с помощью React, к клиентским веб-сайтам и приложениям. ReactDomServer, ReactNative и React360 также являются библиотеками, которые вы можете изучить для использования интерфейсов React в других средах.
Помимо предоставления вспомогательных функций для создания интерфейсов, архитектура React позволяет вам обрабатывать взаимодействия с вашими интерфейсами, будь то обработка событий, вызовы API, управление состоянием, обновления интерфейса или более сложные взаимодействия.
React не предоставляет столько вспомогательных функций, как некоторые фреймворки JavaScript. Во многом поэтому мы называем React библиотекой, а не фреймворком. При работе с React вам все равно придется писать много ванильного JavaScript.
Объяснение архитектуры компонентов React
Компонент — это независимый повторно используемый фрагмент кода (созданный с помощью функции или класса).
React использует компонентную архитектуру для создания пользовательских интерфейсов и организации кода. Основной файл простого приложения React может выглядеть примерно так.
// Импорт React и других компонентов импортировать React из «реагировать»; импортировать {рендеринг} из 'реагировать-дом'; импортировать заголовок из './Header'; импортировать MainContent из './MainContent'; импортировать нижний колонтитул из './Footer'; приложение функции () { возвращение ( <div className="приложение"> <Заголовок/> <Основное содержимое /> <Нижний колонтитул/> </div> ); } ReactDOM.render(<App/>, document.getElementById("root"));
Здесь мы видим несколько используемых компонентов. <Header/>, <MainContent/> и <Footer/> — все это компоненты. Функция App() также является компонентом, и в последней строке этого примера мы можем видеть, как мы можем использовать библиотеку ReactDOM и метод ReactDOM.render() для управления добавлением пользовательского интерфейса, который мы создаем, на веб-страницу.
Если мы углубимся в компоненты <Header />, <MainContent /> и <Footer />, мы, вероятно, увидим использование большего количества компонентов, а также то, что выглядит как HTML-разметка.
импортировать React из «реагировать»; импортировать объявление из "../Ad"; импортировать логотип из "../assets/logo.svg"; функция экспорта по умолчанию Header() { возвращение ( <header className="app-header"> <Объявление /> <img src={logo} className="app-logo" alt="logo" /> <h1 className="app-title">Название сайта</h1> </заголовок> ); }
В этом компоненте <Header /> выше мы видим, что мы подключаем еще один компонент под названием <Ad />. Большинство приложений React содержат несколько уровней вложения компонентов, как мы видим с <App />, <Header /> и <Ad />.
Мы также видим использование элементов HTML в нашем коде React. Это возможно благодаря библиотеке под названием JSX, которая позволяет вам писать «HTML-разметку» непосредственно в вашем JavaScript. Поскольку мы используем React для создания пользовательских интерфейсов, а пользовательские интерфейсы в Интернете включают HTML-разметку, вполне логично, что мы увидим HTML-подобные элементы в наших компонентах пользовательского интерфейса. В этой книге мы подробно изучим JSX.
Если мы посмотрим на некоторый код простого приложения React, созданного с использованием React 360, библиотеки React VR, фактические компоненты, которые мы вызываем, будут другими, но архитектура компонентов все еще присутствует.
импортировать React из «реагировать»; Импортировать { Текст, Вид, ВрКнопка, } из 'реагировать-360'; класс Слайд-шоу расширяет React.Component { // Код удален для краткости возвращение ( <Вид стиля={styles.wrapper}> <Вид стиля={styles.controls}> <VrButton onClick={this.prevPhoto}> <Text>{'Предыдущий'}</Text> </VrButton> <VrButton onClick={this.nextPhoto}> <Text>{'Далее'}</Text> </VrButton> <Вид> <Text style={styles.title}>{current.title}</Text> </Вид> </Вид> ); }
Приведенный выше код создает несколько слоев 360-градусных представлений с некоторыми наложенными кнопками и текстом. Хотя реальный код может не иметь полного смысла, должно быть ясно, что у нас есть несколько вложенных компонентов, представляющих вид, кнопки и текст.
Это хороший пример, потому что вы можете увидеть, как одни и те же компоненты повторно используются по-разному, передавая им разные параметры или то, что React называет props. Понимание того, как данные проходят через компоненты React, важно для понимания типичной архитектуры компонентов, используемой для сборки с помощью React.
Объяснение потока данных React
React следует соглашению о получении и установке данных в самой высокой точке, необходимой в иерархии компонентов, чтобы данные проходили в одном направлении вниз через приложение. Давайте рассмотрим этот пример и представим некоторые типы данных, которые нам понадобятся. для различных компонентов.
приложение функции () { возвращение( <React.Fragment> <Заголовок/> <Содержание/> <Боковая панель /> <Нижний колонтитул/> </React.Fragment> ); }
Что-то вроде названия сайта должно быть доступно как для <Header/>, так и для <Footer/>. Основной контент для конкретной страницы должен быть передан в <Content />. Некоторые дополнительные данные виджета могут потребоваться для перехода на <боковую панель />.
приложение функции () { const siteTitle = getSiteTitle(); константные виджеты = getWidgets(); const mainContent = getPageContent(); возвращение( <React.Fragment> <Заголовок siteTitle={siteTitle} /> <Контент mainContent={mainContent} /> <виджеты боковой панели={виджеты} /> <Нижний колонтитул siteTitle={siteTitle} /> </React.Fragment> ); }
Это соглашение о создании имен атрибутов и присвоении им значения — это то, как мы передаем данные в компонент.
Теперь <Header/> и <Footer/> имеют доступ к siteTitle, <Content/> имеет доступ к mainContent, а <Sidebar/> имеет доступ к нужным ему виджетам.
Важно отметить, что этот шаблон передачи данных в компонент передает данные только на один уровень. Компоненты внутри <Header /> не будут автоматически получать доступ к siteTitle.

Заголовок функции (реквизит) { возвращение( <заголовок> <p>Здесь мы можем увидеть {props.siteTitle}.</p> <PageHeader siteTitle={props.siteTitle} /> <Подзаголовок страницы /> </заголовок> ); }
Здесь вы можете видеть, что внутри <Header /> мы можем вызвать props.siteTitle и получить доступ к тому значению, которое мы в него передали. Однако, если бы мы хотели получить доступ к siteTitle внутри компонента <PageHeader />, нам также пришлось бы вручную передавать эту информацию.
Когда компонент получает значение в качестве реквизита, он не должен его изменять. Реквизиты должны проходить через дерево компонентов как неизменяемые данные. Это гарантирует, что любой компонент, который ссылается на реквизит, ссылается на то же значение, что и родительский компонент дочерних компонентов.
Значение реквизита должно быть изменено только в том компоненте, который изначально установил значение реквизита и начал передавать его вниз по дереву компонентов. В приведенном выше примере кода компонент <App /> может изменить значение siteTitle, а компоненты <Header /> или <PageHeader /> — нет.
Чтобы понять, как динамические данные обновляются в приложении React, необходимо обсудить состояние и то, как обработчики событий могут передаваться в качестве свойств.
Объяснение состояний компонентов React
Как мы узнали, данные передаются без изменений через компоненты в качестве реквизита. Данные устанавливаются в самом верхнем компоненте дерева, необходимом для того, чтобы все дочерние компоненты передавали необходимую информацию в качестве реквизита.
В некоторых случаях эти данные принимаются один раз и не нуждаются в изменении. Однако во многих случаях эти данные должны оставаться динамическими и иметь возможность обновляться в любой момент времени, и это обновление должно отражаться во всех дочерних компонентах.
Чтобы отслеживать данные, которые изменяются в React, у нас есть объект состояния React и набор вспомогательных функций для обновления значения состояния.
Вот пример счетчика, который будет обновлять себя. Значение счетчика — это значение, которое является динамическим в пределах этого компонента и, следовательно, является хорошим примером того, когда следует полагаться на состояние. Обратите внимание, что для создания компонентов с состоянием мы должны использовать классы JavaScript, а не функции.
класс Counter расширяет компонент { состояние = { счетчик:0 }; handleCount = () => { это.setState({ счетчик: this.state.counter + 1 }); }; оказывать() { возвращение ( <дел> <h1>{this.state.counter}</h1> <button onClick={this.handleCount}>Считать!!</button> </div> ); } }
Теперь важно отметить, что это состояние ограничено только этим компонентом. Значение состояния в счетчике не будет доступно для дочерних или родительских компонентов.
Таким образом, в более сложном примере примера, как показано ниже, нам нужно было бы передать значение счетчика в качестве реквизита в дочерний элемент.
класс Counter расширяет компонент { состояние = { количество: 0 }; handleCount = () => { это.setState({ количество: this.state.count + 1 }); }; оказывать() { возвращение ( <дел> <PageHeader count={this.state.count} /> <button onClick={this.handleCount}>Считать!!</button> </div> ); } }
Свойство счетчика <PageHeader/> обновляется каждый раз, когда мы обновляем состояние в компоненте <Counter/>
функция PageHeader (реквизит) { вернуть <h1>{props.count}</h1>; }
Хорошая вещь в этом подходе заключается в том, что каждый раз, когда состояние обновляется, новое значение будет автоматически передаваться в любые дочерние компоненты со значением реквизита, установленным в состояние.
Это позволяет нам иметь единую точку истины для динамических данных. Источником истины является значение в состоянии, управляемое из одного компонента. Все экземпляры этого значения в дочерних компонентах являются неизменяемыми значениями, полученными как свойства, которые не должны изменяться вне этого компонента.
Компоненты, которые появляются выше этого компонента в иерархии, не будут иметь доступа к этим данным, поскольку они передаются только через свойства. Мы снова видим, почему мы пытаемся устанавливать и управлять состоянием компонентов выше в иерархии, чтобы данные были доступны всем, кому они нужны.
Существуют некоторые другие архитектурные шаблоны, такие как компоненты более высокого порядка и контекстный API, которые позволяют обойти необходимость вручную передавать тонны реквизитов через ваше приложение. Мы рассмотрим их более подробно позже. А пока мы хотим убедиться, что мы поняли этот общий обзор того, как все работает, прежде чем мы начнем сокращать пути.
Обновление состояний компонентов в React
Теперь, что происходит, когда мы хотим вызвать обновление состояния из дочернего компонента?
Представьте, например, что в приведенном выше примере мы хотели иметь компонент <Button />, а не жестко запрограммированную кнопку в нашем основном компоненте <Counter />? На самом деле это довольно распространено в сложных приложениях.
Решением этого в мире React является передача функции обработчика событий, которая обновляет состояние с помощью setState down в качестве реквизита. Тогда его можно будет вызывать из любого дочернего компонента, но действие будет происходить в исходном компоненте, задающем состояние и имеющем возможность его обновления. Существуют и другие шаблоны для этого, но этот подход является самым основным.
Если вы не знакомы с передачей функций в качестве параметров, это полностью допустимый ванильный JavaScript.
Как только состояние будет обновлено, оно будет передано по иерархии компонентов через свойства.
Вот пример того, как это будет выглядеть.
класс Counter расширяет компонент { состояние = { количество: 0 }; handleCount = () => { это.setState({ количество: this.state.count + 1 }); }; оказывать() { возвращение ( <дел> <PageHeader count={this.state.count} /> <Button handleCount={this.handleCount} /> </div> ); } } функция PageHeader (реквизит) { возвращение( <h1>{props.count}</h1> ); } функциональная кнопка (реквизит) { возвращение( <button onClick={props.handleCount}>Считать!!</button> ); }
Здесь мы видим простой пример того, как React обрабатывает поток данных. Существует единственная точка истины для данных. Это существует в наборе состояний и обновляется из одного компонента. Данные передаются односторонним потоком вниз по вложенному дереву компонентов через реквизиты.
Если состояние необходимо обновить из компонента, отличного от того, где оно было изначально установлено, то обработчик событий может быть передан необходимому дочернему компоненту в качестве реквизита. Благодаря этому данные остаются неизменными и передаются в одном направлении, потому что даже если дочерний компонент инициирует изменение, это изменение происходит выше в исходном компоненте.
Когда мы присваиваем значение свойства чему-либо из состояния, как показано ниже, это значение свойства будет автоматически обновляться при каждом изменении состояния.
<PageHeader counter={this.state.count} />
Любой другой дочерний компонент, который ссылается на это значение свойства, также получит обновление автоматически. В этом прелесть потока данных в React.
Это может занять некоторое время, чтобы привыкнуть, в зависимости от того, как вы подходили к подобным проблемам с помощью JavaScript в прошлом. Тем не менее, все это должно послужить хорошей отправной точкой для того, чтобы мы могли углубиться в объяснение React.