React с нуля: Подробное руководство для начинающих
React – это JavaScript-библиотека с открытым исходным кодом, разработанная Facebook, которая используется для создания пользовательских интерфейсов (UI), особенно для одностраничных приложений. Благодаря своей компонентной архитектуре, декларативному стилю и виртуальному DOM, React значительно упрощает разработку сложных, интерактивных веб-приложений. Это руководство предназначено для начинающих разработчиков, желающих изучить React с самых основ. Мы шаг за шагом пройдем все этапы – от настройки среды разработки до создания простого React-приложения.
Что такое React и почему он так популярен?
React – это не фреймворк, а именно библиотека. Это означает, что React фокусируется на одной конкретной задаче – управлении отображением данных в UI. Основные преимущества React, которые делают его популярным:
- Компонентная архитектура: React позволяет разбивать UI на небольшие, переиспользуемые компоненты. Это упрощает разработку, поддержку и масштабирование приложения.
- Декларативный подход: Вместо того, чтобы вручную манипулировать DOM, вы описываете, как UI должен выглядеть в зависимости от данных. React автоматически обновляет DOM при изменении данных.
- Виртуальный DOM: React использует виртуальный DOM – легковесное представление реального DOM. Когда данные изменяются, React сравнивает виртуальный DOM с предыдущей версией и обновляет только те части реального DOM, которые действительно изменились. Это значительно повышает производительность.
- JSX: React использует JSX – расширение JavaScript, которое позволяет писать HTML-подобный код непосредственно в JavaScript. Это делает код более читаемым и понятным.
- Большое сообщество и экосистема: React имеет огромное и активное сообщество разработчиков, что означает обилие библиотек, инструментов и обучающих материалов.
Необходимые знания
Прежде чем начать изучать React, вам необходимо обладать базовыми знаниями:
- HTML: Основы структуры веб-страниц.
- CSS: Основы стилизации веб-страниц.
- JavaScript: Базовые знания синтаксиса, переменных, функций, объектов и массивов. Понимание концепций ES6+ (let, const, arrow functions, classes, modules) будет большим плюсом.
- Node.js и npm (или yarn): Node.js используется для запуска инструментов разработки, а npm (или yarn) – для управления пакетами.
Настройка среды разработки
Прежде чем приступить к написанию кода, необходимо настроить среду разработки. Мы будем использовать create-react-app
– инструмент, который автоматически настраивает все необходимое для разработки React-приложения.
1. Установка Node.js и npm (или yarn)
Убедитесь, что у вас установлены Node.js и npm (или yarn). Вы можете скачать и установить Node.js с официального сайта: https://nodejs.org/. npm обычно устанавливается вместе с Node.js. Yarn – альтернативный менеджер пакетов, который можно установить отдельно: https://yarnpkg.com/.
Чтобы проверить, установлены ли Node.js и npm, откройте терминал (или командную строку) и выполните следующие команды:
node -v
npm -v
Если вы видите версии Node.js и npm, значит, они установлены правильно.
2. Установка create-react-app
create-react-app
– это инструмент командной строки, который позволяет быстро создать новое React-приложение. Установите его глобально с помощью npm:
npm install -g create-react-app
Или с помощью yarn:
yarn global add create-react-app
3. Создание нового React-приложения
Теперь создадим новое React-приложение с помощью create-react-app
. В терминале перейдите в каталог, где вы хотите создать проект, и выполните следующую команду:
create-react-app my-app
Замените my-app
на имя вашего приложения. create-react-app
создаст новый каталог с именем вашего приложения и установит все необходимые зависимости.
4. Запуск приложения
После завершения установки перейдите в каталог вашего приложения:
cd my-app
И запустите приложение:
npm start
Или:
yarn start
Это запустит сервер разработки, и ваше приложение автоматически откроется в браузере (обычно по адресу http://localhost:3000
). Вы увидите страницу приветствия React.
Структура проекта create-react-app
create-react-app
создает проект со следующей структурой:
my-app/ node_modules/ public/ index.html favicon.ico ... src/ App.js App.css index.js index.css logo.svg ... package.json ...
node_modules
: Содержит все установленные зависимости проекта.public
: Содержит статические файлы, такие какindex.html
, favicon и другие ресурсы.index.html
– это основной HTML-файл, в который будет внедрено ваше React-приложение.src
: Содержит исходный код вашего React-приложения.App.js
: Основной компонент приложения.App.css
: Стили для компонентаApp.js
.index.js
: Точка входа в приложение. Здесь React рендерит компонентApp
в DOM.index.css
: Глобальные стили для приложения.logo.svg
: Логотип React.package.json
: Файл, содержащий метаданные проекта, такие как имя, версия, зависимости и скрипты.
Основы React: Компоненты, JSX и Props
Компоненты
В React все является компонентом. Компоненты – это переиспользуемые блоки UI, которые могут содержать HTML, CSS и JavaScript. Существует два типа компонентов:
- Функциональные компоненты: Это простые JavaScript-функции, которые принимают
props
в качестве аргументов и возвращают JSX. - Классовые компоненты: Это JavaScript-классы, которые расширяют класс
React.Component
. Они имеют методrender()
, который возвращает JSX. Классовые компоненты также могут иметь состояние (state
) и методы жизненного цикла.
Начнем с функционального компонента. Откройте файл src/App.js
и замените его содержимое следующим:
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
</header>
</div>
);
}
export default App;
Этот код создает функциональный компонент App
, который возвращает JSX, содержащий заголовок и параграф.
JSX
JSX – это расширение JavaScript, которое позволяет писать HTML-подобный код непосредственно в JavaScript. JSX преобразуется в обычный JavaScript-код во время сборки. Основные особенности JSX:
- Встраивание JavaScript: Вы можете встраивать JavaScript-выражения в JSX с помощью фигурных скобок
{}
. - Атрибуты: Атрибуты HTML-элементов в JSX записываются в стиле camelCase (например,
className
вместоclass
). - Один корневой элемент: Каждый JSX-компонент должен возвращать один корневой элемент. Если вам нужно вернуть несколько элементов, оберните их в один родительский элемент (например,
<div>
или<React.Fragment>
).
В примере выше мы использовали JSX для создания HTML-структуры компонента App
. Обратите внимание на использование className
вместо class
для указания класса CSS.
Props
Props (сокращение от properties) – это способ передачи данных от родительского компонента к дочернему. Props являются неизменяемыми (read-only) внутри дочернего компонента.
Создадим новый компонент Greeting
, который будет принимать имя в качестве prop:
Создайте файл src/Greeting.js
со следующим содержимым:
import React from 'react';
function Greeting(props) {
return <h2>Привет, {props.name}!</h2>;
}
export default Greeting;
Этот компонент принимает prop name
и отображает приветствие с использованием этого имени.
Теперь импортируем и используем компонент Greeting
в App.js
:
import React from 'react';
import './App.css';
import Greeting from './Greeting';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<Greeting name="John" />
<Greeting name="Jane" />
</header>
</div>
);
}
export default App;
В этом примере мы передаем props name
со значениями “John” и “Jane” компоненту Greeting
. В браузере вы увидите два приветствия: “Привет, John!” и “Привет, Jane!”.
Состояние (State)
Состояние (state) – это данные, которые компонент хранит и управляет ими. В отличие от props, состояние может изменяться внутри компонента. Изменение состояния вызывает перерисовку компонента, что позволяет React обновлять UI при изменении данных.
Состояние обычно используется в классовых компонентах. Функциональные компоненты могут использовать состояние с помощью хука useState
(который мы рассмотрим позже).
Преобразуем компонент App
в классовый компонент и добавим состояние:
import React, { Component } from 'react';
import './App.css';
import Greeting from './Greeting';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {this.state.count}</p>
<Greeting name="John" />
<Greeting name="Jane" />
</header>
</div>
);
}
}
export default App;
В этом примере мы добавили состояние count
в компонент App
. Состояние инициализируется в конструкторе компонента. Мы отображаем значение состояния count
в параграфе.
Изменение состояния
Для изменения состояния в классовых компонентах используется метод setState()
. setState()
принимает объект с новыми значениями состояния и планирует перерисовку компонента.
Добавим кнопку, которая будет увеличивать значение счетчика при нажатии:
import React, { Component } from 'react';
import './App.css';
import Greeting from './Greeting';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.incrementCount = this.incrementCount.bind(this);
}
incrementCount() {
this.setState({
count: this.state.count + 1
});
}
render() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {this.state.count}</p>
<button onClick={this.incrementCount}>Увеличить</button>
<Greeting name="John" />
<Greeting name="Jane" />
</header>
</div>
);
}
}
export default App;
В этом примере мы добавили метод incrementCount()
, который увеличивает значение состояния count
на 1. Мы также добавили кнопку, которая вызывает метод incrementCount()
при нажатии. Обратите внимание на использование this.incrementCount.bind(this)
в конструкторе. Это необходимо для того, чтобы this
внутри метода incrementCount()
указывал на экземпляр компонента.
Обработка событий
React позволяет обрабатывать различные события, такие как клики, наведение мыши, ввод текста и т.д. Обработчики событий в React записываются в JSX с использованием атрибутов, начинающихся с on
(например, onClick
, onChange
, onMouseOver
). Значением атрибута является функция, которая будет вызвана при возникновении события.
В предыдущем примере мы уже использовали обработчик события onClick
для кнопки. Рассмотрим другой пример – обработка события onChange
для текстового поля:
import React, { Component } from 'react';
import './App.css';
import Greeting from './Greeting';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
inputValue: ''
};
this.incrementCount = this.incrementCount.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
incrementCount() {
this.setState({
count: this.state.count + 1
});
}
handleInputChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {this.state.count}</p>
<button onClick={this.incrementCount}>Увеличить</button>
<input type="text" value={this.state.inputValue} onChange={this.handleInputChange} />
<p>Вы ввели: {this.state.inputValue}</p>
<Greeting name="John" />
<Greeting name="Jane" />
</header>
</div>
);
}
}
export default App;
В этом примере мы добавили текстовое поле и обработчик события onChange
. Функция handleInputChange()
вызывается при каждом изменении текста в текстовом поле. Она обновляет состояние inputValue
значением из текстового поля. Мы также отображаем значение inputValue
в параграфе.
Условный рендеринг
Условный рендеринг позволяет отображать разные элементы UI в зависимости от условий. В React есть несколько способов реализации условного рендеринга:
- If/else: Используйте операторы
if
иelse
для выбора, какой элемент отображать. - Тернарный оператор: Используйте тернарный оператор
condition ? trueValue : falseValue
для выбора между двумя значениями. - Короткое замыкание (&&): Используйте оператор
&&
для отображения элемента только если условие истинно.
Добавим условный рендеринг, чтобы отображать сообщение, если счетчик больше 5:
import React, { Component } from 'react';
import './App.css';
import Greeting from './Greeting';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
inputValue: ''
};
this.incrementCount = this.incrementCount.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
incrementCount() {
this.setState({
count: this.state.count + 1
});
}
handleInputChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {this.state.count}</p>
<button onClick={this.incrementCount}>Увеличить</button>
<input type="text" value={this.state.inputValue} onChange={this.handleInputChange} />
<p>Вы ввели: {this.state.inputValue}</p>
{this.state.count > 5 && <p>Счетчик больше 5!</p>}
<Greeting name="John" />
<Greeting name="Jane" />
</header>
</div>
);
}
}
export default App;
В этом примере мы используем оператор &&
для отображения параграфа “Счетчик больше 5!”, только если состояние count
больше 5.
Списки и ключи
В React часто приходится отображать списки данных. Для этого используются массивы и метод map()
для преобразования массива данных в массив React-элементов.
При отображении списков React требует, чтобы каждый элемент имел уникальный атрибут key
. Ключи помогают React идентифицировать элементы списка и эффективно обновлять DOM при изменении данных. В качестве ключа обычно используется уникальный идентификатор элемента (например, ID из базы данных).
Создадим список имен и отобразим их с помощью компонента Greeting
:
import React, { Component } from 'react';
import './App.css';
import Greeting from './Greeting';
class App extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
inputValue: '',
names: ['John', 'Jane', 'Peter', 'Mary']
};
this.incrementCount = this.incrementCount.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
incrementCount() {
this.setState({
count: this.state.count + 1
});
}
handleInputChange(event) {
this.setState({
inputValue: event.target.value
});
}
render() {
const nameList = this.state.names.map((name, index) => (
<Greeting key={index} name={name} />
));
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {this.state.count}</p>
<button onClick={this.incrementCount}>Увеличить</button>
<input type="text" value={this.state.inputValue} onChange={this.handleInputChange} />
<p>Вы ввели: {this.state.inputValue}</p>
{this.state.count > 5 && <p>Счетчик больше 5!</p>}
{nameList}
</header>
</div>
);
}
}
export default App;
В этом примере мы создаем массив nameList
, который содержит компоненты Greeting
для каждого имени в массиве names
. Мы используем индекс элемента в качестве ключа (в реальном приложении следует использовать уникальный идентификатор).
Хуки (Hooks)
Хуки – это нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React в функциональных компонентах. Основные хуки:
useState
: Позволяет добавлять состояние в функциональные компоненты.useEffect
: Позволяет выполнять побочные эффекты (например, запросы к API, подписки на события) в функциональных компонентах.useContext
: Позволяет получать доступ к контексту (данные, доступные для всех компонентов в дереве) в функциональных компонентах.
useState
useState
– это хук, который позволяет добавлять состояние в функциональные компоненты. Он принимает начальное значение состояния в качестве аргумента и возвращает массив из двух элементов:
- Текущее значение состояния.
- Функция для обновления состояния.
Перепишем компонент App
с использованием хука useState
:
import React, { useState } from 'react';
import './App.css';
import Greeting from './Greeting';
function App() {
const [count, setCount] = useState(0);
const [inputValue, setInputValue] = useState('');
const names = ['John', 'Jane', 'Peter', 'Mary'];
const incrementCount = () => {
setCount(count + 1);
};
const handleInputChange = (event) => {
setInputValue(event.target.value);
};
const nameList = names.map((name, index) => (
<Greeting key={index} name={name} />
));
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {count}</p>
<button onClick={incrementCount}>Увеличить</button>
<input type="text" value={inputValue} onChange={handleInputChange} />
<p>Вы ввели: {inputValue}</p>
{count > 5 && <p>Счетчик больше 5!</p>}
{nameList}
</header>
</div>
);
}
export default App;
В этом примере мы используем useState
для создания состояний count
и inputValue
. Функции setCount()
и setInputValue()
используются для обновления этих состояний.
useEffect
useEffect
– это хук, который позволяет выполнять побочные эффекты в функциональных компонентах. Побочные эффекты – это операции, которые выполняются после рендеринга компонента (например, запросы к API, подписки на события). useEffect
принимает два аргумента:
- Функцию, которая будет выполнена после рендеринга.
- Массив зависимостей. Если любая из зависимостей изменится, функция будет выполнена снова. Если массив зависимостей пуст, функция будет выполнена только один раз при монтировании компонента.
Добавим побочный эффект, который будет устанавливать заголовок страницы при изменении счетчика:
import React, { useState, useEffect } from 'react';
import './App.css';
import Greeting from './Greeting';
function App() {
const [count, setCount] = useState(0);
const [inputValue, setInputValue] = useState('');
const names = ['John', 'Jane', 'Peter', 'Mary'];
useEffect(() => {
document.title = `Счетчик: ${count}`;
}, [count]);
const incrementCount = () => {
setCount(count + 1);
};
const handleInputChange = (event) => {
setInputValue(event.target.value);
};
const nameList = names.map((name, index) => (
<Greeting key={index} name={name} />
));
return (
<div className="App">
<header className="App-header">
<h1>Привет, React!</h1>
<p>Это мое первое React-приложение.</p>
<p>Счетчик: {count}</p>
<button onClick={incrementCount}>Увеличить</button>
<input type="text" value={inputValue} onChange={handleInputChange} />
<p>Вы ввели: {inputValue}</p>
{count > 5 && <p>Счетчик больше 5!</p>}
{nameList}
</header>
</div>
);
}
export default App;
В этом примере мы используем useEffect
для установки заголовка страницы при каждом изменении состояния count
. Массив зависимостей содержит только count
, поэтому функция будет выполнена только при изменении count
.
Заключение
В этом руководстве мы рассмотрели основные концепции React, такие как компоненты, JSX, props, состояние, обработка событий, условный рендеринг, списки и ключи, а также хуки. Это только начало вашего путешествия в мир React. Существует множество других тем, которые стоит изучить, такие как:
- Маршрутизация: Использование библиотек, таких как
react-router-dom
, для создания многостраничных приложений. - Управление состоянием: Использование библиотек, таких как
Redux
илиContext API
, для управления состоянием в сложных приложениях. - Тестирование: Написание тестов для проверки правильности работы ваших компонентов.
- Оптимизация производительности: Использование техник, таких как мемоизация и ленивая загрузка, для повышения производительности приложения.
Продолжайте изучать React, экспериментировать с кодом и строить свои собственные проекты. Удачи!