▸ 1. Що таке React?
React — це JavaScript бібліотека для створення користувацького інтерфейсу. Вона дозволяє будувати UI з компонентів та ефективно оновлювати DOM за допомогою Virtual DOM.
import React from 'react';
import ReactDOM from 'react-dom';
function App() {
return <h1>Hello React!</h1>;
}
ReactDOM.render(<App />, document.getElementById('root'));
Best practice: завжди розбивай UI на маленькі компоненти для повторного використання.
▸ 2. Що таке JSX?
JSX — це синтаксичне розширення для JavaScript, що дозволяє писати HTML-подібний код у JS. React трансформує JSX у виклики React.createElement.
const element = <h1>Hello, JSX!</h1>;
Правило: JSX повинен бути обгорнутий у один кореневий елемент.
▸ 3. Функціональні та класові компоненти
Функціональні компоненти — це прості функції, що повертають JSX. Класові компоненти розширюють React.Component і мають додаткові можливості, як state і lifecycle.
// Функціональна
function Greeting() {
return <h2>Hello!</h2>;
}
// Класова
class GreetingClass extends React.Component {
render() {
return <h2>Hello Class!</h2>;
}
}
Best practice: з React 16+ рекомендується використовувати функціональні компоненти з hooks.
▸ 4. Props
Props — це властивості, які передаються компоненту для налаштування його поведінки. Вони є тільки для читання.
function Welcome(props) {
return <h2>Hello, {props.name}</h2>;
}
<Welcome name="Alice" />;
Правило: ніколи не змінюйте props всередині компонента.
▸ 5. State
State — це внутрішній стан компонента, який може змінюватися з часом і викликає повторний рендеринг компонента.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
Best practice: тримайте state мінімальним і локалізованим.
▸ 6. Події у React
Події у React обробляються через camelCase атрибути, наприклад onClick, onChange.
function Button() {
const handleClick = () => alert('Clicked!');
return <button onClick={handleClick}>Click me</button>;
}
Правило: не викликайте функцію у JSX без обгортки, інакше вона виконається одразу.
▸ 7. Умовний рендеринг
React дозволяє умовно рендерити елементи через ? : або &&.
// з ? :
const isLoggedIn = true;
return isLoggedIn ? <p>Welcome back!</p> : <p>Please sign in.</p>
// з &&
return <div>{isLoggedIn && <p>Welcome back!</p>}</div>;
Best practice: використовуйте ternary, якщо є else, && для коротких перевірок.
▸ 8. Fragment у React
React.Fragment дозволяє групувати елементи без додаткового DOM-вузла.
return (
<>
<h1>Title</h1>
<p>Description</p>
</>
);
Правило: зберігає DOM чистим і зменшує непотрібні div.
▸ 9. Коментарі у JSX
Коментарі у JSX пишуться всередині фігурних дужок.
return (
<div>
{/* Це коментар */}
<p>Text</p>
</div>
);
▸ 10. Атрибути у JSX
Деякі HTML-атрибути мають camelCase назви у JSX, наприклад className, htmlFor.
<input type="text" className="input" readOnly />
<label htmlFor="input">Label</label>
▸ 11. Передача функцій як props
Можна передавати функції з батьківського компонента в дочірній через props, щоб дочірній компонент викликав дії батька.
function Child({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
function Parent() {
const handleClick = () => alert('Clicked from parent!');
return <Child onClick={handleClick} />;
}
Best practice: передавай тільки потрібні функції та уникай створення нових функцій всередині render без необхідності.
▸ 12. Контрольовані компоненти
Контрольований компонент зберігає значення інпуту у state і керує ним через onChange.
function ControlledInput() {
const [value, setValue] = React.useState('');
return <input value={value} onChange={e => setValue(e.target.value)} />;
}
Правило: state є єдиним джерелом істини для значень інпутів.
▸ 13. Неконтрольовані компоненти
Неконтрольований інпут використовує ref для доступу до значення без збереження його у state.
function UncontrolledInput() {
const inputRef = React.useRef();
const handleClick = () => alert(inputRef.current.value);
return <div>
<input ref={inputRef} />
<button onClick={handleClick}>Show Value</button>
</div>;
}
Best practice: використовуй неконтрольовані компоненти лише для простих форм або інтеграції зі сторонніми бібліотеками.
▸ 14. Вставка виразів у JSX
У JSX можна вставляти будь-які JS-вирази у фігурних дужках.
const name = 'Alice';
return <h1>Hello, {name}!</h1>;
Правило: у дужках можна писати вирази, але не statements (if, for, etc.).
▸ 15. Коментарі у JSX
Коментарі повинні бути всередині фігурних дужок: {/* коментар */}
return (
<div>
{/* Це коментар */}
<p>Text</p>
</div>
);
▸ 16. Умовний рендеринг з &&
Зручно використовувати для рендерингу одного елемента за умови true.
const isLoggedIn = true;
return <div>
{isLoggedIn && <p>Welcome back!</p>}
</div>;
Правило: && повертає false, якщо умова невірна, і React нічого не рендерить.
▸ 17. Умовний рендеринг з ? :
Для вибору між двома елементами використовуйте тернарний оператор.
return <div>
{isLoggedIn ? <p>Welcome back!</p> : <p>Please sign in.</p>}
</div>;
▸ 18. Вставка списків у JSX
Списки рендеряться через map(), важливо додавати унікальний key для кожного елемента.
const fruits = ['Apple', 'Banana', 'Cherry'];
return <ul>
{fruits.map((fruit, index) => <li key={index}>{fruit}</li>)}
</ul>;
Best practice: використовуйте стабільні ключі, а не індекси, коли можливо.
▸ 19. Атрибути HTML у JSX
Багато атрибутів змінюють написання у JSX (camelCase), наприклад className, htmlFor.
<input type="text" className="input" readOnly />
<label htmlFor="input">Label</label>
▸ 20. Best practices основ React
- Розбивайте UI на маленькі, повторно використовувані компоненти.
- Використовуйте state лише там, де потрібно відстежувати дані.
- Props не можна змінювати всередині компонентів.
- Функціональні компоненти + hooks — сучасний стандарт.
▸ 21. Списки у React
Списки рендеряться за допомогою функції map()
. Важливо вказувати унікальний key
для кожного елемента.
const fruits = ['Apple', 'Banana', 'Cherry'];
return <ul>
{fruits.map((fruit) => <li key={fruit}>{fruit}</li>)}
</ul>;
Правило: не використовуйте індекси як ключі, якщо порядок елементів може змінюватися.
▸ 22. Умовний рендеринг у списках
Можна рендерити список лише за умови, якщо він не порожній.
return <ul>
{fruits.length > 0
? fruits.map(f => <li key={f}>{f}</li>)
: <li>Список порожній</li>}
</ul>;
▸ 23. Контрольовані форми
Контрольований інпут зберігає значення у state і оновлює його через onChange
.
function ControlledInput() {
const [value, setValue] = React.useState('');
return <input value={value} onChange={e => setValue(e.target.value)} />;
}
▸ 24. Неконтрольовані форми
Неконтрольований інпут використовує ref для доступу до значення без state.
function UncontrolledInput() {
const inputRef = React.useRef();
const handleClick = () => alert(inputRef.current.value);
return <div>
<input ref={inputRef} />
<button onClick={handleClick}>Show</button>
</div>;
}
▸ 25. Обробка подій у формах
Усі події у React обробляються через camelCase атрибути.
function Form() {
const handleChange = e => console.log(e.target.value);
return <input onChange={handleChange} />;
}
▸ 26. Кілька input у state
Можна зберігати значення кількох інпутів у одному об'єкті state.
function Form() {
const [form, setForm] = React.useState({name:'', age:''});
const handleChange = e => setForm({...form, [e.target.name]: e.target.value});
return (
<form>
<input name="name" value={form.name} onChange={handleChange} />
<input name="age" value={form.age} onChange={handleChange} />
</form>
);
}
▸ 27. Списки з компонентами
Можна створювати компонент для елементів списку та рендерити їх через map.
function Item({ value }) {
return <li>{value}</li>;
}
function List() {
const items = ['A', 'B', 'C'];
return <ul>{items.map(v => <Item key={v} value={v} />)}</ul>;
}
▸ 28. Checkbox у формах
Контрольований checkbox керується через state.
function Checkbox() {
const [checked, setChecked] = React.useState(false);
return <input type="checkbox" checked={checked} onChange={e => setChecked(e.target.checked)} />;
}
▸ 29. Select у формах
Select елемент також може бути контрольованим через state.
function Select() {
const [value, setValue] = React.useState('A');
return (
<select value={value} onChange={e => setValue(e.target.value)}>
<option value="A">A</option>
<option value="B">B</option>
</select>
);
}
▸ 30. preventDefault у формах
Для запобігання перезавантаженню сторінки при submit використовується e.preventDefault().
function Form() {
const handleSubmit = e => {
e.preventDefault();
alert('Form submitted!');
};
return <form onSubmit={handleSubmit}><button type="submit">Submit</button></form>;
}
▸ 31. Контрольований textarea
Textarea у React може бути контрольованим компонентом через state.
function TextArea() {
const [text, setText] = React.useState('');
return <textarea value={text} onChange={e => setText(e.target.value)} />;
}
▸ 32. Неконтрольований textarea
Неконтрольований textarea використовує ref для доступу до значення.
function TextArea() {
const ref = React.useRef();
const handleClick = () => alert(ref.current.value);
return <div>
<textarea ref={ref} />
<button onClick={handleClick}>Show</button>
</div>;
}
▸ 33. Додавання динамічних полів форми
Можна додавати input елементи динамічно за допомогою state та map.
function DynamicForm() {
const [inputs, setInputs] = React.useState(['']);
const addInput = () => setInputs([...inputs, '']);
return <div>
{inputs.map((val, i) => <input key={i} value={val} />)}
<button onClick={addInput}>Add</button>
</div>;
}
▸ 34. Обробка числових полів
Інпут type="number" можна контролювати через state і приводити значення до числа.
function NumberInput() {
const [num, setNum] = React.useState(0);
return <input type="number" value={num} onChange={e => setNum(Number(e.target.value))} />;
}
▸ 35. Select з масиву опцій
Можна генерувати опції select динамічно через map.
const options = ['A', 'B', 'C'];
function SelectList() {
const [value, setValue] = React.useState('A');
return (
<select value={value} onChange={e => setValue(e.target.value)}>
{options.map((opt, i) => <option key={i} value={opt}>{opt}</option>)}
</select>
);
}
▸ 36. Валідація форми
Можна перевіряти значення полів перед відправкою форми і показувати повідомлення користувачу.
function Form() {
const [name, setName] = React.useState('');
const handleSubmit = e => {
e.preventDefault();
if(name.trim() === '') alert('Name is required');
};
return <form onSubmit={handleSubmit}>
<input value={name} onChange={e => setName(e.target.value)} />
<button type="submit">Submit</button>
</form>;
}
▸ 37. Кілька checkbox
Можна зберігати стан декількох checkbox у масиві.
function Checkboxes() {
const [checked, setChecked] = React.useState([]);
const toggle = value => {
setChecked(prev => prev.includes(value) ? prev.filter(v => v!==value) : [...prev, value]);
};
return ['A','B','C'].map(val =>
<label key={val}>
<input type="checkbox" checked={checked.includes(val)} onChange={() => toggle(val)} /> {val}
</label>
);
}
▸ 38. Radio buttons
Контрольований radio button вибирає одну опцію з групи.
function Radios() {
const [selected, setSelected] = React.useState('A');
return ['A','B','C'].map(val =>
<label key={val}>
<input type="radio" value={val} checked={selected===val} onChange={e => setSelected(e.target.value)} /> {val}
</label>
);
}
▸ 39. Submit без перезавантаження
Використання e.preventDefault() дозволяє обробляти submit без reload.
function Form() {
const handleSubmit = e => {
e.preventDefault();
alert('Form submitted without reload!');
};
return <form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>;
}
▸ 40. Best practices форм та списків
- Завжди використовуйте унікальні key для списків.
- Керовані форми простіші для відстеження стану.
- Обробляйте submit через preventDefault.
- Валідуйте поля перед відправкою.
▸ 41. useState
useState дозволяє додавати локальний стан у функціональні компоненти.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return <div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>;
}
Правило: не змінюйте state напряму, використовуйте setCount.
▸ 42. useEffect
useEffect дозволяє виконувати побічні ефекти, наприклад запити до API або підписки.
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval); // cleanup
}, []);
return <p>Seconds: {seconds}</p>;
}
Правило: завжди очищайте підписки у return для уникнення memory leaks.
▸ 43. useRef
useRef зберігає mutable значення або DOM-елементи між рендерами.
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef();
return <div>
<input ref={inputRef} />
<button onClick={() => inputRef.current.focus()}>Focus</button>
</div>;
}
Best practice: useRef не викликає ререндер при зміні значення.
▸ 44. useMemo
useMemo запам'ятовує результат обчислень для оптимізації продуктивності.
import React, { useMemo, useState } from 'react';
function Expensive({ num }) {
const compute = useMemo(() => {
console.log('Computing...');
return num * 2;
}, [num]);
return <p>Result: {compute}</p>;
}
Правило: використовуйте useMemo тільки для дорогих обчислень.
▸ 45. useCallback
useCallback запам'ятовує функцію між рендерами, щоб уникнути зайвих перерендерів дочірніх компонентів.
import React, { useState, useCallback } from 'react';
function Button({ onClick }) {
console.log('Button render');
return <button onClick={onClick}>Click</button>;
}
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => setCount(c => c + 1), []);
return <div>
<Button onClick={handleClick} />
<p>Count: {count}</p>
</div>;
}
▸ 46. useContext
useContext дозволяє отримати значення з Context без передачі через props.
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function Child() {
const theme = useContext(ThemeContext);
return <p>Theme: {theme}</p>;
}
function Parent() {
return <ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>;
}
▸ 47. Кастомні хуки
Кастомні хуки — це функції, що використовують інші хуки і повертають логіку для повторного використання.
import React, { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
function App() {
const width = useWindowWidth();
return <p>Width: {width}</p>;
}
▸ 48. useLayoutEffect
useLayoutEffect виконується синхронно після DOM оновлення, до відображення на екрані.
import React, { useLayoutEffect, useRef } from 'react';
function Measure() {
const ref = useRef();
useLayoutEffect(() => {
console.log(ref.current.getBoundingClientRect());
}, []);
return <div ref={ref}>Measure me</div>;
}
▸ 49. useImperativeHandle
useImperativeHandle дозволяє налаштувати, що повертає ref при використанні forwardRef.
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const Input = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus()
}));
return <input ref={inputRef} />;
});
function App() {
const ref = useRef();
return <div>
<Input ref={ref} />
<button onClick={() => ref.current.focus()}>Focus</button>
</div>;
}
▸ 50. useReducer
useReducer — альтернатива useState для складних станів із діями.
import React, { useReducer } from 'react';
function reducer(state, action) {
switch(action.type) {
case 'increment': return {count: state.count + 1};
case 'decrement': return {count: state.count - 1};
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, {count:0});
return <div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({type:'increment'})}>+</button>
<button onClick={() => dispatch({type:'decrement'})}>-</button>
</div>;
}
▸ 51. useDebugValue
useDebugValue дозволяє відображати інформацію для кастомних хуків у React DevTools.
import React, { useDebugValue } from 'react';
function useCustomHook(value) {
useDebugValue(value ? 'Has Value' : 'No Value');
return value;
}
▸ 52. useDeferredValue
useDeferredValue дозволяє відкласти оновлення частини UI для кращої продуктивності.
import React, { useState, useDeferredValue } from 'react';
function Search() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return <input value={query} onChange={e => setQuery(e.target.value)} />;
}
▸ 53. useTransition
useTransition допомагає позначити оновлення як низькоприоритетні для плавного UI.
import React, { useState, useTransition } from 'react';
function App() {
const [isPending, startTransition] = useTransition();
const [value, setValue] = useState(0);
const handleClick = () => {
startTransition(() => setValue(v => v + 1));
};
return <div>
<button onClick={handleClick}>Increment</button>
<p>Value: {value}</p>
</div>;
}
▸ 54. useId
useId генерує унікальний id для елементів, зручний для label та input.
import React, { useId } from 'react';
function Input() {
const id = useId();
return <div>
<label htmlFor={id}>Name</label>
<input id={id} />
</div>;
}
▸ 55. useSyncExternalStore
useSyncExternalStore використовується для синхронізації з зовнішніми станами (store) у React 18+.
import { useSyncExternalStore } from 'react';
function useStore(store) {
return useSyncExternalStore(store.subscribe, () => store.getState());
}
▸ 56. useEffect cleanup
Функція, яку повертає useEffect, використовується для очищення ефектів (event listeners, таймери).
useEffect(() => {
const id = setInterval(() => console.log('Tick'), 1000);
return () => clearInterval(id);
}, []);
▸ 57. useState з функцією ініціалізації
Можна передати функцію для початкового стану, щоб обчислення відбулося лише один раз.
const [value, setValue] = useState(() => expensiveComputation());
▸ 58. useEffect залежності
Масив залежностей визначає, коли ефект повторно виконується.
useEffect(() => {
console.log(value);
}, [value]); // ефект виконується при зміні value
▸ 59. Порядок хуків
Хуки завжди повинні викликатися в одному порядку всередині компоненту або кастомного хуку.
// Правильно
useState();
useEffect();
// Неправильно
if(condition) useState(); // ❌
▸ 60. Best practices хуків
- Використовуйте функціональні компоненти з хуками.
- Дотримуйтесь правил виклику хуків (не всередині умов або циклів).
- Використовуйте useMemo та useCallback для оптимізації складних обчислень або ререндерів.
- Чистіть ефекти через return у useEffect.
- Виносьте логіку у кастомні хуки для повторного використання.
▸ 61. React Router - BrowserRouter
BrowserRouter обгортає додаток і дозволяє використовувати маршрути.
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return <BrowserRouter>
<Routes>
<Route path="/" element=<Home /> />
<Route path="/about" element=<About /> />
</Routes>
</BrowserRouter>;
}
▸ 62. Route та element
Route визначає шлях і компонент, який рендериться через element.
<Route path="/contact" element=<Contact /> />
▸ 63. useParams
useParams дозволяє отримати параметри з URL.
import { useParams } from 'react-router-dom';
function User() {
const { id } = useParams();
return <p>User ID: {id}</p>;
}
▸ 64. useNavigate
useNavigate дозволяє програмно переміщатися між сторінками.
import { useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
return <button onClick={() => navigate('/about')}>Go to About</button>;
}
▸ 65. useLocation
useLocation дає доступ до об'єкта location (path, search, state).
import { useLocation } from 'react-router-dom';
function Page() {
const location = useLocation();
return <p>Current path: {location.pathname}</p>;
}
▸ 66. Context API - createContext
createContext створює глобальний контекст для передачі даних без props drilling.
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function Child() {
const theme = useContext(ThemeContext);
return <p>Theme: {theme}</p>;
}
function App() {
return <ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>;
}
▸ 67. Context Provider та Consumer
Provider дає значення, Consumer або useContext отримує його.
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>;
▸ 68. Redux - основи
Redux управляє глобальним станом через store, actions та reducers.
import { createStore } from 'redux';
const initialState = { count: 0 };
function reducer(state = initialState, action) {
switch(action.type) {
case 'increment': return { count: state.count + 1 };
default: return state;
}
}
const store = createStore(reducer);
▸ 69. Redux - connect та useSelector/useDispatch
useSelector читає стан, useDispatch відправляє дії.
import { useSelector, useDispatch } from 'react-redux';
function Counter() {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return <div>
<p>Count: {count}</p>
<button onClick={() => dispatch({type:'increment'})}>+</button>
</div>;
}
▸ 70. Zustand - базовий стан
Zustand - легкий глобальний state management для React.
import create from 'zustand';
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 }))
}));
function Counter() {
const { count, increment } = useStore();
return <div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>;
}
▸ 71. React.lazy
React.lazy дозволяє завантажувати компонент асинхронно для оптимізації bundle.
import React, { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return <Suspense fallback=<p>Loading...</p>>
<LazyComponent />
</Suspense>;
}
▸ 72. Suspense fallback
fallback показує UI під час завантаження lazy-компоненту.
<Suspense fallback=<div>Loading...</div>>
<LazyComponent />
</Suspense>
▸ 73. Nested routes
React Router дозволяє вкладені маршрути для компонентів.
<Routes>
<Route path="/" element=<Layout />>
<Route path="about" element=<About /> />
</Route>
</Routes>
▸ 74. Redirect / Navigate
useNavigate дозволяє здійснювати перенаправлення після дії користувача.
const navigate = useNavigate();
<button onClick={() => navigate('/login')}>Go to Login</button>
▸ 75. Protected routes
Створюються для обмеження доступу до певних сторінок.
function Protected({ children }) {
const auth = useAuth();
return auth ? children : <Navigate to="/login" />;
}
▸ 76. Lazy load images / components
Використовуйте React.lazy та Suspense для компонентів, а loading="lazy" для зображень.
<img src="image.jpg" loading="lazy" />
▸ 77. useReducer + Context
Поєднання useReducer та Context дозволяє глобальний state без Redux.
const CountContext = createContext();
function reducer(state, action) {
switch(action.type) {
case 'inc': return { count: state.count+1 };
default: return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, {count:0});
return <CountContext.Provider value={{state, dispatch}}>
<Child />
</CountContext.Provider>;
}
▸ 78. Global state з Zustand
Zustand дозволяє легко керувати глобальним станом без boilerplate.
import create from 'zustand';
const useStore = create(set => ({
user: null,
setUser: user => set({user})
}));
function Profile() {
const {user, setUser} = useStore();
}
▸ 79. Suspense + Data fetching
Suspense можна використовувати для рендеру компонентів після завантаження даних.
const Resource = React.lazy(() => import('./DataComponent'));
<Suspense fallback=<div>Loading...</div>>
<Resource />
</Suspense>
▸ 80. Best practices стану та маршрутизації
- Використовуйте React Router для маршрутизації, а useNavigate для переходів.
- Global state можна реалізувати через Context, Redux або Zustand.
- Lazy та Suspense покращують продуктивність додатка.
- Використовуйте Protected routes для авторизації.
- Дотримуйтесь структурованого розподілу state між локальним і глобальним.
▸ 81. Portals
Portals дозволяють рендерити дочірні елементи поза DOM-структурою батьківського компоненту.
import ReactDOM from 'react-dom';
function Modal({ children }) {
return ReactDOM.createPortal(
<div className="modal">{children}</div>,
document.getElementById('modal-root')
);
}
▸ 82. Error Boundaries
Компоненти Error Boundary ловлять помилки в дочірніх компонентах та рендерять fallback UI.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) { return { hasError: true }; }
render() { return this.state.hasError ? <h1>Something went wrong</h1> : this.props.children; }
}
▸ 83. useId для доступності
useId забезпечує унікальні id для input та label для кращої доступності.
const id = useId();
<label htmlFor={id}>Name</label>
<input id={id} />
▸ 84. Server Components
Server Components рендеряться на сервері, зменшуючи JS на клієнті.
export default function ServerComponent() {
return <div>Rendered on server</div>;
}
▸ 85. Next.js Pages
Next.js використовує файли в папці pages для автоматичної маршрутизації.
// pages/index.js
export default function Home() {
return <h1>Home Page</h1>;
}
▸ 86. Next.js API routes
API маршрути створюються в папці pages/api та повертають JSON.
// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello API' });
}
▸ 87. React Testing Library - базове
Для тестування компонентів React використовується render та fireEvent.
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('increments counter', () => {
render(<Counter />);
fireEvent.click(screen.getByText('+'));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
▸ 88. React Profiler
Profiler вимірює час ререндеру компонентів.
<Profiler id="App" onRender={(id, phase, actualDuration) => console.log(actualDuration)}>
<App />
</Profiler>
▸ 89. Memoization компонентів
React.memo запобігає перерендеру компоненту, якщо props не змінились.
const Button = React.memo(({onClick, label}) => <button onClick={onClick}>{label}</button>);
▸ 90. useTransition для плавного UI
Позначає оновлення як низькоприоритетні для плавнішого UI.
const [isPending, startTransition] = useTransition();
startTransition(() => setState(newValue));
▸ 91. useDeferredValue
Відкладає оновлення значення для оптимізації рендеру важких компонентів.
const deferredValue = useDeferredValue(value);
▸ 92. useId для форм
Генерує унікальні id для input та label, покращує доступність.
const id = useId();
<label htmlFor={id}>Email</label>
<input id={id} />
▸ 93. React Profiler API
Profiler дозволяє вимірювати час ререндеру компонентів для оптимізації продуктивності.
<Profiler id="App" onRender={(id, phase, actualDuration) => console.log(actualDuration)}>
<App />
</Profiler>
▸ 94. Suspense для даних
Suspense може використовуватись не лише для lazy-компонентів, але й для асинхронних даних.
<Suspense fallback=<div>Loading data...</div>>
<DataComponent />
</Suspense>
▸ 95. Concurrent React
Concurrent режим дозволяє React пріоритетно обробляти оновлення та покращує UX.
import { startTransition } from 'react';
startTransition(() => setState(newValue));
▸ 96. Оптимізація рендеру
- Використовуйте React.memo для компонентів, які не повинні часто перерендерюватися.
- useCallback для запобігання створенню нових функцій при кожному рендері.
- useMemo для запобігання дорогим обчисленням на кожен рендер.
▸ 97. Error boundaries для компонентів
Використовуйте класові компоненти для ловлі помилок у дочірніх компонентах.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
render() { return this.state.hasError ? <h1>Something went wrong</h1> : this.props.children; }
}
▸ 98. Portals для модальних вікон
Portals рендерять модальні компоненти поза основним DOM, у зручний контейнер.
ReactDOM.createPortal(<Modal />, document.getElementById('modal-root'));
▸ 99. Next.js оптимізація
- Використовуйте getStaticProps та getServerSideProps для оптимізації рендеру.
- Lazy loading компонентів та зображень.
- Image optimization через next/image.
▸ 100. Best practices просунутих тем
- Використовуйте Error Boundaries для стабільності додатка.
- Lazy та Suspense для покращення UX та продуктивності.
- Portals для модальних компонентів.
- Concurrent features та useDeferredValue/useTransition для плавного UI.
- Next.js – оптимізація серверного рендеру та статичних сторінок.
- Тестування через React Testing Library та профайлинг рендерів.