React
Компоненты
export default function Button() { return <button>Click me</button>;}
Вставка переменных в шаблон
export const HomePage = () => { const number = 8; function fibonacci(n) { if (n <= 1) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } return ( <div> <p>Это число: {number}</p> <p>Это число умноженное на 2: {number * 2}</p> <p>Это число фибоначчи: {fibonacci(number)}</p> </div> );};
Рендеринг коллекций
export const HomePage = () => { const students = [ { id: 1, fullName: "John", age: 20, gpa: 3.5 }, { id: 2, fullName: "Jane", age: 21, gpa: 3.7 }, { id: 3, fullName: "Bob", age: 19, gpa: 3.2 }, { id: 4, fullName: "Alice", age: 22, gpa: 3.8 }, ];
return ( <div> <h1>Студенты</h1> <ul> {students.map((student) => ( <li key={student.id}> {student.fullName} - {student.age} лет, {student.gpa} GPA </li> ))} </ul> </div> );};
Props
interface ButtonProps { children: React.ReactNode; onClick: () => void;}
export default function Button(props: ButtonProps) { return <button onClick={props.onClick}>{props.children}</button>;}
Hooks
useState
import { useState } from "react";
const Counter = () => { const [count, setCount] = useState(0); // count — текущее значение, setCount — функция обновления
return ( <div> <p>Счетчик: {count}</p> <button onClick={() => setCount(count + 1)}>+</button> </div> );};
useEffect
1. Запуск эффекта при каждом рендере (без зависимостей)
import { useState, useEffect } from "react";
function Counter() { const [count, setCount] = useState(0);
useEffect(() => { console.log("Компонент обновился!"); });
return ( <div> <p>Счетчик: {count}</p> <button onClick={() => setCount(count + 1)}>Увеличить</button> </div> );}
🔍 Что происходит?
- useEffect вызывается после каждого рендера (в том числе после обновления состояния count).
- В консоли после каждого клика будет сообщение “Компонент обновился!”.
🔴 Минус: может вызывать ненужные вычисления, если эффект не должен запускаться при каждом рендере.
2. Запуск эффекта один раз (при монтировании компонента)
Если передать пустой массив зависимостей [], эффект выполнится только один раз – при первом рендере.
import { useEffect } from "react";
function HelloWorld() { useEffect(() => { console.log("Компонент был смонтирован!"); }, []);
return <p>Привет, мир!</p>;}
🔍 Что происходит?
- Сообщение “Компонент был смонтирован!” появится только один раз после монтирования.
📌 Применение:
- Запрос данных (fetch)
- Подписка на глобальные события (window.addEventListener)
- Установка начального состояния (localStorage.getItem)
3. Запуск эффекта при изменении зависимостей
Если передать массив зависимостей, эффект будет срабатывать только при изменении этих зависимостей.
import { useState, useEffect } from "react";
function UserProfile({ userId }) { const [userData, setUserData] = useState(null);
useEffect(() => { console.log(`Загружаем данные для пользователя ${userId}`);
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`) .then((response) => response.json()) .then((data) => setUserData(data)); }, [userId]); // Запускается только при изменении userId
return <p>Пользователь: {userData?.name || "Загрузка..."}</p>;}
🔍 Что происходит?
- useEffect сработает при первом рендере и каждый раз, когда изменяется userId.
- Если userId не меняется — эффект не выполняется повторно.
📌 Применение:
- Переключение между пользователями (например, при выборе ID)
- Запрос новых данных при изменении параметров
- Обновление стилей или заголовков страницы
4. Очистка эффекта (Cleanup)
Некоторые эффекты (например, таймеры или подписки) требуют очистки перед размонтированием компонента или перед повторным вызовом эффекта.
import { useState, useEffect } from "react";
function Timer() { const [seconds, setSeconds] = useState(0);
useEffect(() => { const interval = setInterval(() => { setSeconds((prev) => prev + 1); }, 1000);
return () => { clearInterval(interval); // Очистка таймера при размонтировании console.log("Таймер остановлен!"); }; }, []); // Таймер запускается только при монтировании
return <p>Секунды: {seconds}</p>;}
🔍 Что происходит?
- setInterval запускается при монтировании.
- Когда компонент размонтируется, вызывается clearInterval, чтобы предотвратить утечки памяти.
📌 Применение:
- Отписка от событий (window.removeEventListener)
- Очистка таймеров (clearTimeout, clearInterval)
- Закрытие соединений (WebSocket, AbortController)
5. Очистка перед каждым новым вызовом
Если эффект зависит от переменной, React сначала очистит предыдущий эффект перед вызовом нового.
import { useState, useEffect } from "react";
function MouseTracker() { const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => { const updateMousePosition = (event) => { setPosition({ x: event.clientX, y: event.clientY }); };
window.addEventListener("mousemove", updateMousePosition);
return () => { window.removeEventListener("mousemove", updateMousePosition); console.log("Очистка: отписка от mousemove"); }; }, []);
return ( <p> Координаты мыши: {position.x}, {position.y} </p> );}
🔍 Что происходит?
- При монтировании подписка window.addEventListener(“mousemove”, updateMousePosition).
- Если компонент размонтируется, вызывается removeEventListener, чтобы избежать утечек памяти.
📌 Применение:
- Отписка от глобальных событий
- Удаление старых подписок перед добавлением новых
- Завершение анимаций или запросов
useRef
import { useRef } from "react";
function Counter() { const countRef = useRef(0);
useEffect(() => { console.log(countRef.current); }, [countRef.current]);
return ( <div> <p>Счетчик: {countRef.current}</p> <button onClick={() => countRef.current++}>+</button> </div> );}