Ось готовий урок, створений за твоїм майстер-промптом. Я зберіг енергетику та структуру CS50, адаптувавши це під український контекст та тему React (оскільки "Component State" найчастіше стосується саме його).
🎓 CS50: State (Стан) — Пам'ять ваших компонентів
Привіт, друзі! Радий вас бачити. 👋
Сьогодні ми поговоримо про магію, яка перетворює статичні картинки на екрані на живі, інтерактивні додатки. Ми поговоримо про State (Стан).
1. 🔥 Вступ: Проблема «Рибки Дорі»
Уявіть, що ви прийшли до ресторану. Ви дивитесь у меню — воно красиве, ламіноване. Це — Props (властивості). Меню надрукували в типографії, принесли вам, і воно незмінне. Ви не можете пальцем стерти ціну і написати свою, правда ж?
Але ось підходить офіціант із блокнотом. Ви кажете: «Я буду борщ». Він записує. Потім ви передумали: «Ні, давайте вареники». Він закреслює борщ, пише вареники. Його блокнот змінюється в реальному часі.
У чому проблема веб-сторінок без стану? Вони як рибка Дорі з мультика «У пошуках Немо». У них немає короткочасної пам'яті.
Погляньте на звичайну змінну в функції компонента:
function Counter() {
let count = 0; // Звичайна змінна
const handleClick = () => {
count = count + 1;
console.log(count); // В консолі буде 1, 2, 3...
};
return <button onClick={handleClick}>{count}</button>;
}
Ви можете клікати хоч тисячу разів. У консолі цифри змінюються, але на екрані вперто світиться 0. Чому? Тому що React не знає, що треба оновити картинку. Звичайна змінна помирає щоразу, коли функція завершує роботу.
Без State ваші додатки — це просто цифрові плакати. Зі State — це інструменти.
2. 🧠 Теоретична база: Що там «під капотом»?
Давайте визначимося.
State (Стан) — це внутрішня пам'ять компонента, яка дозволяє йому запам'ятовувати інформацію між оновленнями екрану (рендерами).
Коли ви змінюєте State, ви не просто змінюєте цифру. Ви натискаєте на "тривожну кнопку" 🚨, яка кричить React'у: «Гей! Дані змінилися! Перемалюй цей шматочок інтерфейсу негайно!»
Як це працює (логіка, а не просто код):
- Ініціалізація: Компонент народжується, ми даємо йому початкове значення (наприклад,
0). - Знімок (Snapshot): React робить "фотографію" компонента з цим значенням і показує її користувачу.
- Подія: Користувач клікає кнопку.
- Зміна стану: Ми просимо React змінити значення.
- Ре-рендер: React викидає стару "фотографію", створює нову з новим значенням і замінює її на екрані.
🔑 Що треба запам'ятати (Hook useState):
У React (та багатьох сучасних бібліотеках) ми використовуємо спеціальний інструмент — хук.
const [count, setCount] = useState(0);
Уявіть це як коробку:
* count (змінна): Те, що зараз лежить у коробці. Тільки для читання!
* setCount (функція): Єдиний спосіб покласти в коробку щось нове.
* useState(0): Початковий вміст коробки.
Інтуїтивне розуміння: Ніколи не змінюйте count напряму (count = 5). Це як намагатися перевести стрілки годинника силою, не крутячи коліщатко — ви просто зламаєте механізм. Використовуйте setCount(5).
3. 🧪 Приклади (від простого до реального)
Приклад 1: Класичний лічильник
(Те, що ми намагалися зробити на початку, але тепер правильно)
❓ Питання до вас: Що відбудеться на екрані, коли я натисну кнопку, якщо використаю код нижче?
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Кліків: {count}
</button>
);
}
Пояснення: На екрані цифра зміниться з 0 на 1. Виклик setCount змусив React запустити функцію Counter знову, але цього разу змінна count вже дорівнює 1.
Приклад 2: Перемикач "Світло/Темрява" (Булевий стан)
Це найчастіший кейс: відкрити меню, поставити лайк, показати модальне вікно.
function LightSwitch() {
// true = увімкнено, false = вимкнено
const [isOn, setIsOn] = useState(false);
return (
<div style={{ background: isOn ? 'yellow' : 'gray' }}>
<p>Світло {isOn ? 'УВІМКНЕНО 💡' : 'ВИМКНЕНО 🌑'}</p>
<button onClick={() => setIsOn(!isOn)}>
Клацнути вимикачем
</button>
</div>
);
}
❓ Чому ми пишемо !isOn?
Це означає "зроби навпаки від того, що є зараз". Якщо було true, стане false, і навпаки. Це елегантно і просто.
Приклад 3: Введення тексту (Input)
Реальна задача: форма реєстрації або пошук.
❓ Питання: Якщо я друкую на клавіатурі, як React дізнається, які букви я натискаю?
function TextInput() {
const [text, setText] = useState('');
return (
<div>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Введіть ваше ім'я..."
/>
<p>Привіт, {text}!</p>
</div>
);
}
Пояснення: Це називається "контрольований компонент".
1. Ви натискаєте "A".
2. Подія onChange хапає цю букву.
3. setText оновлює пам'ять.
4. React перемальовує input, вставляючи туди "A".
Усе це відбувається за мілісекунди!
4. 🛠 Практична частина
Час закачати рукави! Відкривайте редактор коду (або CodeSandbox) і спробуйте:
- 🔹 Повторення: Скопіюйте приклад із лічильником (
Counter). Переконайтеся, що він працює. - 🔹 Зміна умов: Зробіть так, щоб лічильник не додавав +1, а віднімав -1.
- 🔹 Виправлення помилки:
У вас є код:
javascript const [score, setScore] = useState(10); // ... десь у коді onClick={() => score = 20}Виправте його так, щоб React побачив зміни. - 🔹 Реальна задача: Створіть кнопку «Показати спойлер».
- Спочатку на екрані кнопка і текст "Секретна інформація прихована".
- При натисканні текст змінюється на "Вбивця — дворецький!", а напис на кнопці стає "Сховати".
- 🔹 Міні-кейс «Твіттер»:
Створіть
textarea. Під ним показуйте лічильник символів.- Якщо символів менше 100 — колір лічильника зелений.
- Якщо більше 100 — червоний.
- 🔹 А що, якщо... Створіть два лічильники в одному компоненті. Натисніть на один. Чи зміниться значення іншого? Чому?
5. 💡 Мислення як у розробника
Як відрізнити новачка від профі, дивлячись на роботу зі станом?
❌ Типові помилки новачків:
- Зайвий стейт. Зберігають те, що можна вирахувати.
- Погано:
firstName,lastName,fullName(всі три в стейті). - Добре:
firstName,lastNameв стейті. Аconst fullName = firstName + ' ' + lastName— просто змінна під час рендеру.
- Погано:
- Мутація об'єктів.
- Погано:
user.name = "Ivan"; setUser(user);(React не побачить змін, бо посилання на об'єкт старе). - Добре:
setUser({ ...user, name: "Ivan" });(Новий об'єкт, нове посилання).
- Погано:
🧠 Як думає Senior:
Він ставить собі питання: «Чи є це мінімально необхідною інформацією, яка змінюється з часом?»
Якщо я можу вирахувати це з props або інших змінних — це не State.
State — це джерело істини. Чим менше джерел, тим чистіша вода (і менше багів).
6. 🧩 Підсумок
Отже, що ми сьогодні розібрали?
- State — це пам'ять компонента. Без неї інтерфейс мертвий.
- Зміна State викликає ре-рендер (оновлення картинки).
- Ми використовуємо
useState: одне значення читаємо, функцією — змінюємо.
Тепер ви вмієте: Створювати кнопки, які реагують на натискання, форми, які запам'ятовують текст, і інтерфейси, що змінюються динамічно. Ви вдихнули життя у свій код!
🔮 Що далі?
Зараз наш State живе тільки всередині одного компонента. Але що, як ми хочемо передати інформацію з «верхнього» компонента (Батька) до «нижнього» (Дитини)? Наступного разу ми розберемо Props та те, як дані подорожують вашим додатком.
Це був CS50. Побачимось! 💻