Основы React
React - JavaScript библиотека для отображения интерфейса пользователя (UI).
React vs JavaScript
JavaScript: императивный подход — достижение результата с помощью выполнения последовательности действий.
React: декларативный подход — подробное описание конечного результата.
Компоненты
Приложения на React состоят из компонентов. Компонент - это часть пользовательского интерфейса, которая имеет свою логику и внешний вид. Он может быть маленьким, как кнопка, или большим, как целая страница.
Если часть UI используется несколько раз или достаточно сложна сама по себе, ее делают отдельным компонентом.
Компонент React представляет собой JavaScript функцию, возвращающую разметку. Имя компонента всегда начинается с заглавной буквы, в то время как HTML-тег должен начинаться с маленькой.
Написание JSX разметки
JSX представляет из себя объекты. Babel компилирует JSX в вызовы React.createElement().
const element = <h1 className="greeting">Привет, мир!</h1>;
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Привет, мир!'
);
Синтаксис JSX необязателен, однако способствует читаемости кода, так как очень похож на HTML, но более строгий к синтаксису.
JSX позволяет вкладывать в него JavaScript с помощью фигурных скобок. Значения атрибутов в JSX также могут быть JavaScript выражениями, для этого вместо кавычек необходимо использовать фигурные скобки.
Написание тегов
Необходимо всегда закрывать одинарные теги, такие как <br />.
Компонент не может возвращать несколько JSX тегов. Необходимо обернуть их в общий родительский или использовать пустую обертку <>...</> (React Fragment).
Установка атрибутов
Установка атрибутов с помощью JSX происходит в стиле camelCase:
const element = <div tabIndex="0"></div>;
Написание стилей
Инлайн стили можно передать в виде объекта со свойствами в camelCase:
<div style={{ backgroundColor: 'black', color: 'red'}}></div>
Еще больше о JSX
Логические значения, null и undefined игнорируются
Эти выражения будут представлены одной и той же строкой:
<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
Для того, чтобы вывести их явно, необходимо использовать преобразование в строку:
<div>
Моя переменная JavaScript: {String(myVariable)}.
</div>
Строковые литералы
JSX удаляет пробел в начале и конце строки, также удаляя пустые строки, а новые линии в середине строки конвертируются в единственный пробел.
Следующие два выражения эквивалентны:
<div>
Hello
World
</div>
<div>Hello World</div>
Свойства props
Когда React видит элемент, представляющий пользовательский компонент, он передаёт JSX-атрибуты этому компоненту в виде единственного объекта, называемого props. Свойства объекта props доступны только для чтения.
export default function App() {
return (
<div>
<Welcome name="Сара" />
<Welcome name="Эдит" />
</div>
);
}
function Welcome(props) {
return <h1>Привет, {props.name}</h1>;
}
Свойство children
В свойстве children содержатся вложенные в компонент элементы, о которых сам компонент может не знать.
export default function App() {
return (
<div>
<Welcome name="Сара">Привет,</Welcome>
<Welcome name="Эдит">Привет,</Welcome>
</div>
);
}
function Welcome(props) {
return <h1>{props.children} {props.name}</h1>;
}
Свойства по умолчанию
Если не передать значение в JSX, оно по умолчанию будет true. Следующие два выражения эквивалентны:
<MyTextBox autocomplete />
<MyTextBox autocomplete={true} />
Отрисовка по условию
Для написания условий используется синтаксис JavaScript: if..else, тернарный оператор, логическое И.
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
Отрисовка списка
Элемент списка должен иметь атрибут key c уникальным значением. Значение атрибута key должно быть уникальным только среди соседних элементов, а не глобально. Лучше всего для этого подойдет id элемента..
Чтобы для каждого элемента списка отобразить несколько DOM-узлов, необходимо явно импортировать Fragment (сокращенный синтаксис <></> не позволяет указывать атрибут key):
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Чистые компоненты
Некоторые JavaScript функции называются чистыми. Чистые функции:
- Не изменяют переменные снаружи функции.
- Для одинаковых входных данных результат работы функции будет неизменным.
Компоненты, написанные как чистые функции, позволяют избежать многих ошибок и непредсказуемого поведения по мере роста приложения.
Например, если требуется использовать методы push, pop, reverse, sort для данных в props, необходимо сначала сделать копию этих данных.
Обновление отрисованного элемента
React-элементы неизменяемы. Создав однажды элемент, нельзя изменить его дочерние элементы или атрибуты. Единственный способ обновить интерфейс — создать новый элемент и передать его в ReactDOM.render().
function tick() {
const element = (
<div>
<h1>Привет, мир!</h1>
<h2>Сейчас {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.createRoot(document.getElementById('root')).render(element);
}
setInterval(tick, 1000);
На практике большинство приложений React только один раз вызывают метод render().
React обновляет только то, что необходимо
DOM React сравнивает элемент и его дочерние элементы с предыдущими и применяет только обновления DOM, необходимые для преобразования DOM в желаемое состояние.
Создание приложения
Чтобы начать использовать React, можно воспользоваться готовыми утилитами или выполнить настройку проекта вручную.
Create React App
npx create-react-app <project-directory>
npm start запускает локальный сервер.
Использование с Typescript
npx create-react-app <project-directory> --template typescript
Vite
npm create vite@latest
Далее перейти в папку с проектом cd <project-directory> и установить зависимости npm install.
npm run dev запускает локальный сервер.
Настройка вручную
Пример пошаговой настройки проекта вручную:
npm initсоздать package.json.npm i react react-domустановить необходимые пакеты.npm i -D webpack webpack-cli webpack-dev-server html-webpack-pluginустановить пакеты для разработки.- Добавить в package.json скрипты:
"dev": "webpack serve --mode development", "build": "webpack --mode production", - Создать в корне проекта папку src, а в ней файл index.js.
- В index.js написать:
import React from 'react' import ReactDOM from 'react-dom/client' ReactDOM.createRoot(document.getElementById('root')).render(<div>Контент</div>) - Создать в корне папку public, а в ней index.html.
- В index.html создать структуру страницы и добавить корневой элемент
<div id="root"></div>. npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loaderустановить Babel.- Создать в корне проекта файл конфига .babelrc с содержимым:
{ "presets": ["@babel/preset-env", "@babel/preset-react"] } - Создать в корне проекта файл конфига webpack.config.js c содержимым:
const HtmlWebpackPlugin = require("html-webpack-plugin"); const path = require('path'); module.exports = { mode: "development", entry: "./src/index.js", output: { filename: 'bundle.js', }, module: { rules: [ { test: /\.(jsx|js)$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, { test: /\.css$/, use: [ "style-loader", { loader: "css-loader", options: { importLoaders: 1, modules: true, }, }, ], }, ], }, resolve: { extensions: [".js", ".jsx"], }, plugins: [ new HtmlWebpackPlugin({ template: "./public/index.html", }), ], devServer: { port: 3000, static: { directory: path.join(__dirname, "dist"), }, hot: true, open: true, }, }; npm i -D style-loader css-loaderдобавить поддержку CSS-модулей (использование:import * as classes from './<file>.module.css').- Добавить файл .gitignore с содержимым:
/node_modules/ /dist/
Деплой на github pages
Create React App
Последовательность действий:
npm install gh-pages --save-dev- Добавить в package.json:
"homepage": "https://<username>.github.io/<repo>/", ... "scripts": { "predeploy": "npm run build", "deploy": "gh-pages -d dist", ... } - Выполнить команду
npm run deploy.
React Router
При использовании библиотеки react-router-dom следует заменить BrowserRouter на HashRouter.
Vite app
Добавить base: "/<repo>/", в vite.config.js, затем выполнить те же шаги, что и для Create React App.