Введение
React - это популярная библиотека JavaScript для создания пользовательских интерфейсов. В этой статье мы рассмотрим основы React и научимся создавать современные веб-приложения.
Что такое React?
- Компонентность: Переиспользуемые UI-элементы
- Виртуальный DOM: Эффективное обновление
- JSX: Декларативный синтаксис
- Односторонний поток данных: Предсказуемое поведение
Начало работы
1. Установка и настройка
Создание проекта
1
2
3
4
5
6
7
8
| # Создание нового проекта
npx create-react-app my-app
# Переход в директорию проекта
cd my-app
# Запуск приложения
npm start
|
Структура проекта
1
2
3
4
5
6
7
8
9
10
11
12
| my-app/
├── node_modules/
├── public/
│ ├── index.html
│ └── favicon.ico
├── src/
│ ├── components/
│ ├── pages/
│ ├── App.js
│ └── index.js
├── package.json
└── README.md
|
2. Базовый JSX
Синтаксис JSX
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // Простой компонент
function App() {
return (
<div className="app">
<h1>Привет, React!</h1>
<p>Это мое первое приложение</p>
</div>
);
}
// Вложенные элементы
function Navigation() {
return (
<nav>
<ul>
<li><a href="/">Главная</a></li>
<li><a href="/about">О нас</a></li>
<li><a href="/contact">Контакты</a></li>
</ul>
</nav>
);
}
|
Компоненты
1. Функциональные компоненты
Создание компонента
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // Простой компонент
function Button({ text, onClick }) {
return (
<button onClick={onClick}>
{text}
</button>
);
}
// Использование компонента
function App() {
return (
<div>
<Button
text="Нажми меня"
onClick={() => alert('Привет!')}
/>
</div>
);
}
|
2. Классовые компоненты
Создание классового компонента
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment() {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Счет: {this.state.count}</p>
<button onClick={() => this.increment()}>
Увеличить
</button>
</div>
);
}
}
|
Хуки
1. useState
Управление состоянием
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
return (
<div>
<p>Счет: {count}</p>
<button onClick={() => setCount(count + 1)}>
Увеличить
</button>
<input
value={text}
onChange={(e) => setText(e.target.value)}
/>
<p>Текст: {text}</p>
</div>
);
}
|
2. useEffect
Побочные эффекты
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Загрузка данных
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
});
}, []); // Пустой массив зависимостей
if (loading) return <p>Загрузка...</p>;
return <div>{JSON.stringify(data)}</div>;
}
|
Управление состоянием
1. Props
Передача данных
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| // Родительский компонент
function App() {
const user = {
name: 'John',
age: 30
};
return (
<div>
<UserProfile user={user} />
</div>
);
}
// Дочерний компонент
function UserProfile({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>Возраст: {user.age}</p>
</div>
);
}
|
2. Context
Глобальное состояние
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| import { createContext, useContext, useState } from 'react';
// Создание контекста
const ThemeContext = createContext();
// Провайдер
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
// Использование
function ThemeToggle() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Переключить тему
</button>
);
}
|
Маршрутизация
1. React Router
Настройка маршрутизации
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Главная</Link>
<Link to="/about">О нас</Link>
<Link to="/contact">Контакты</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
|
2. Защищенные маршруты
Реализация
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| function PrivateRoute({ children }) {
const isAuthenticated = useAuth(); // Ваш хук для проверки авторизации
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return children;
}
// Использование
<Route
path="/dashboard"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
/>
|
Оптимизация
1. Мемоизация
useMemo и useCallback
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| import { useMemo, useCallback } from 'react';
function ExpensiveComponent({ data }) {
// Мемоизация вычислений
const processedData = useMemo(() => {
return data.map(item => ({
...item,
processed: true
}));
}, [data]);
// Мемоизация функций
const handleClick = useCallback(() => {
console.log('Clicked!');
}, []);
return (
<div>
{processedData.map(item => (
<div key={item.id} onClick={handleClick}>
{item.name}
</div>
))}
</div>
);
}
|
2. Ленивая загрузка
Реализация
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import { lazy, Suspense } from 'react';
// Ленивая загрузка компонента
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Загрузка...</div>}>
<HeavyComponent />
</Suspense>
</div>
);
}
|
Тестирование
1. Jest и React Testing Library
Написание тестов
1
2
3
4
5
6
7
8
9
10
11
12
13
| import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('увеличивает счетчик при клике', () => {
render(<Counter />);
const button = screen.getByText('Увеличить');
const count = screen.getByText('Счет: 0');
fireEvent.click(button);
expect(count).toHaveTextContent('Счет: 1');
});
|
2. Тестирование хуков
Кастомные хуки
1
2
3
4
5
6
7
8
9
10
11
12
| import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('увеличивает счетчик', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
|
Заключение
React - это мощный инструмент для создания современных веб-приложений. Понимание основ React и правильное использование его возможностей поможет создавать качественные и масштабируемые приложения.