
Это первая из двух статей (нажмите здесь, чтобы посмотреть вторую), посвященных очень популярной JavaScript библиотеке - React. Данная библиотека широко используется в проектах нашей компании. В этой статье я решил рассмотреть основные концепты этой библиотеки, чтобы незнакомый с React читатель мог получить представление как устроена работа с ней.
За основу статьи был взят источник "Every React Concept Explained in 12 Minutes" by Code Bootcamp.
1 Компоненты (components)
Давайте начнем с компонентов.
Компоненты - это строительные блоки любого приложения на React. Они позволяют нам реализовать все видимые части наших приложений, например, кнопки, поля ввода, и даже страницы целиком. Подобно деталям конструктора Лего, вы можете использовать компоненты столько раз, сколько вам необходимо.
<Header />
<Content />
<Footer />
<CoolButton/>
Каждый компонент в React - JavaScript функция, которая возвращает разметку.
2 JSX
Но так как React - это все же JavaScript библиотека, компоненты React не возвращают разметку HTML в чистом виде, они возвращают так называемый JSX (JavaScript XML), который является замаскированным JavaScript.
function CoolButton() {
//обратите внимание, что название функции пишется в pascal case
return <button>Click me</button>
}
Стоит отметить, что использование JSX не является обязательным. Альтернативным способом создания UI является использование функции "create element".
createElement('button', null, 'Click me')
Однако необходимость постоянно писать и вызывать эту функцию быстро надоедает и подавляющее большинство разработчиков её не используют, а используют JSX.
Так как JSX - это по сути JavaScript, вы не можете писать атрибуты в разметке JSX, так как это разрешено в HTML, - все атрибуты должны быть записаны в стиле camel case. Это к примеру означает, что такие атрибуты как class, которые допустимы в HTML, должны быть записаны с учетом camel case - в нашем примере, мы получим атрибут className.
Неправильно:
<button class="btn"></button>
Правильно:
<button className="btn"></button>
3 Фигурные скобки (curly braces)
В отличии от Html, который является статическим и неизменяемым, преимущество использования React заключается в том, что вы можете использовать изменяемые (динамические) переменные/значения в JSX. Если вы хотите отобразить данные, вы можете сделать это в JSX с помощью фигурных скобок.
Фигурные скобочки принимают напрямую такие типы данных, как строки, числа.
const planet = 'world'
<div>Hello {planet} </div>
Вы можете использовать их, чтобы сделать аттрибуты динамическими.
const src = /react.svg"
<img src={src} />
И вы можете стилизовать элементы React, используя объекты JavaScript внутри фигурных скобок.
const background = 'red'
<div style={{background}} />
4 Фрагменты (Fragments)
В связи с особенностями работы функций JavaScript, в React можно вернуть только один родительский элемент из компонента.
Например, сделать так не получится, будет ошибка (JSX expressions must have one parent element):
function App () {
return (
<Header />
<Main />
)
}
Мы можем исправить это, обернув эти компоненты в div.
<div>
<Header/>
<Main/>
</div>
Однако, добавлять еще один элемент, не несущий полезной нагрузки, на страницу не всегда является подходящим решением. Подходящим решением является использование пустого компонента, называемого React Fragment:
<>
<Header/>
<Main/>
</>
5 Свойства, реквизиты (Props)
Как быть если мы хотим передать данные в какой-либо компонент?
Для этого используются так называемые props.
Для того, чтобы создать prop, у компонента, в который нужно передать данные, необходимо написать имя аттрибута и задать ему требуемое значение. Все очень просто:
<Greeting text = {'Hello from tune-it'} />
Далее, можно пользоваться этим prop внутри компонента:
function Greeting(props) {
return <h1>{props.text} </h1>
}
Props относятся к свойствам объекта, которые доступны в параметрах каждого компонента, и вызываются из объекта с помощью обычного синтаксиса JavaScript (через точку):
props.text
Повторимся еще раз, по сути, props - это пользовательские атрибуты, которые вы можете добавить к любому компоненту.
6 Дочерние компоненты (Children)
В качестве prop можно передавать в компонент что-угодно, даже другие компоненты.
Если вы поместите между тегами компонента другие компоненты, как здесь:
<Parent>
<Child1/>
<Child2/>
</Parent>
Вы получите родительский компонент, и заключенные в нем, дочерние компоненты.
Для доступа к дочерним компонентам используется свойство children родительского компонента.
function Parent (props) {
return <div>{props.children}</div>
}
Дочерние компоненты служат для создания так называемой композиции, которая заключается в организации компонентов react наиболее оптимальным образом.
Свойство children полезно для создания layout компонентов, когда вы хотите, чтобы ваши дочерние компоненты имели одинаковый общий макет.
7 Ключи (Keys)
Ключ - это встроенное в React свойство, которое используется для того, чтобы React мог отличать один компонент от другого.
Ключи часто используются при создании списков. Ключ - это просто уникальная строка или число для идентификации компонента.
{items.map(item=> (
<Component key="{item.id}" />
))}
В случаях когда необходимо добавить ключ и вы забыли это сделать, React предупредит вас об этом в консоли:
Warning: Each child in a list should have a unique "key" prop.
Если у вас нет возможности предоставить уникальное значение для каждого элемента, вы всегда можете использовать текущий индекс из функции map:
{items.map((item, index)=> (
<div key={index}>{item}</div>
))}
8 Отрисовка (Rendering)
Rendering - это процесс преобразования написанного нами кода в код, понятный браузеру, с целью дальнейшего отображения информации пользователю, в доступной для понимания форме.
React выполняет отрисовку за нас. Однако, важно понимать как работает этот процесс, чтобы не допустить случаев, когда наш код приводит к бесконечной отрисовк и падению приложения:
function App() {
const [count, setCount] = useState(0)
useEffect(()=>
{
setCount(count + 1)
// упс! бесконечный цикл
}, [count])
}
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Технология, с помощью которой React знает, как и когда отрисовывать наше приложение, под капотом использует нечто, называемое виртуальным DOM, также известным как vDOM.
Что такое DOM? DOM означает Document Object Model - объектную модель документа. Эту модель использует каждый браузер для создания дерева html-элементов, присутствующих на странице.
Процесс отрисовки в React упрощенно состоит из трех основных шагов:
1) Если состояние нашего React приложения меняется, то React обновляет виртуальный Dom, который обновляется быстрее, чем реальный Dom.
2) Затем React использует процесс, называемый Diffing, чтобы сравнить обновленный виртуальный Dom с его предыдущей версией, чтобы определить, что конкретно изменилось.
3) Как только React находит отличия, запускается процесс, называемый Reconciliation, и происходит обновление реального Dom теми изменениями, которые были найдены.
9 Обработка событий
Каждый раз, когда кто-то использует наше приложение, происходит множество событий со стороны пользователей, таких как: щелчки мышью, движения мышью, а также нажатия на клавиши клавиатуры. Многие из этих событий мы должны обнаружить и правильно на них отреагировать. Весь этот процесс называется обработкой событий.
React упрощает обработку событий тем, что имеет встроенную поддержку многих часто используемых событий. Например, к таким события можно причислить: onclick, onchange, onsubmit.
<button onClick = {handleClick} />
<input onChange = {handleChange} />
<form onSubmit = {handleSubmit} />
К примеру, мы хотим оповестить пользователей, что была нажата кнопка.
Для этого, нам нужно добавить свойство onClick к кнопке и привязать его к функции, которая отобразит оповещение.
function Alert() {
const handleClick = () => {
alert ('tune-it team can solve your IT problems')
}
return(
<button onClick = {handleClick}>
Contact tune-it
</button>
)
}
10 Cостояние (State)
Для управления данными в React-приложениях используется Состояние.
Состояние - это как снимок (snapshot) с фото-камеры. Это "фотография" нашего приложения в любой отдельно взятый момент времени.
Для управления состоянием мы не можем использовать обычные Javascript переменные (let, const), так как они не вызывают переотрисовку (re-render) нашего приложения.
Для управления состоянием мы используем специальные функции, такие как: useState(), useReducer().
Рассмотрим пример:
const [requests, setRequests] = useState(0)
Функция useState принимает аргумент, который служит начальным значением для переменной состояния (useState(0) - начальное значение равно нулю), которая в данном примере является requests, и возвращает массив, содержащий переменную состояния и функцию для обновления этого состояния ([requests, setRequests]).
Рассмотрим снова пример с кнопкой.
function CallMeRequests() {
const [requests, setRequests] = useState(0)
const handleClick = () => {
setRequests(requests + 1)
}
return(
<button onClick = {handleClick}>
Click me for support request from tune-it.
Already requested: {requests} time(-s)
</button>
)
}
В этом примере, каждый раз при нажатии на кнопку, происходит обновление значения переменной состояния requests (увеличивается на единичку), происходит автоматическая переотрисовка приложения (так как используется useState), новое значение переменной отображается пользователю.
11 Управляемые компоненты (Controlled Components)
Управляемые компоненты используют значения состояний для более предсказуемого поведения.
Вот пример управляемого компонента:
function ControlledInput() {
const[value, setValue] = useState('')
return (
<input
value={value}
onChange={(e)=> setValue(e.target.value)} />
)
}
Здесь значение, вводимое в компонент input, помещается в Состояние и управляется значением переменной состояния.
Пользователь набирает текст, setValue помещает то, что он набрал, в Состояние.
Затем значение состояния обновляется, и, наконец, компонент ввода использует обновленное Состояние в качестве своего значения.
Управляемые компоненты - отличный паттерн для использования, потому что, если мы хотим изменить поведение компонента, нам нужно просто изменить состояние, которое управляет им.
На этом пока все
В следующей части мы продолжим рассматривать основные концепты React и коснемся таких концептов, как: Hooks, Purity, Strict Mode, Effects, Refs, Context, Portals, Suspense и Error Boundaries.
Оставайтесь с нами :)