Соберите управляемую форму с несколькими полями и чекбоксом. При отправке покажите собранные данные и очистите форму.
Бизнес-кейс. LeadCapture — мини-форма лида: имя, email, сообщение и согласие на рассылку.
onChange.onSubmit соберите объект данных и отобразите его ниже.Карточка с полями формы, чекбоксом, кнопкой отправки и блоком «Отправлено».
Превью:

const [name, setName] = useState('') и аналогично для остальных.disabled={!name.trim() || !email.trim()}.onSubmit: e.preventDefault(); собрать { name, email, message, subscribe }, показать, затем очистить поля.canSubmit в переменную для читабельности.import React, { useState } from 'react';
import './styles.css';
export function FeedbackForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const [subscribe, setSubscribe] = useState(false);
const [submitted, setSubmitted] = useState(null);
function handleSubmit(e) {
e.preventDefault();
const canSubmit = name.trim() && email.trim();
if (!canSubmit) return;
setSubmitted({ name, email, message, subscribe });
setName('');
setEmail('');
setMessage('');
setSubscribe(false);
}
const canSubmit = name.trim() && email.trim();
return (
<article className="card" data-testid="form-card">
<header>
<h2 className="title">LeadCapture: форма обратной связи</h2>
<p className="subtitle">Управляемые поля + чекбокс, отправка формы</p>
</header>
<form className="row" onSubmit={handleSubmit} aria-label="form">
<input
className="input"
type="text"
placeholder="Имя"
value={name}
onChange={(e) => setName(e.target.value)}
aria-label="name"
/>
<input
className="input"
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
aria-label="email"
/>
<textarea
className="textarea"
placeholder="Сообщение"
value={message}
onChange={(e) => setMessage(e.target.value)}
aria-label="message"
rows={3}
/>
<label className="checkbox-row">
<input
className="checkbox"
type="checkbox"
checked={subscribe}
onChange={(e) => setSubscribe(e.target.checked)}
aria-label="subscribe"
/>
<span>Подписаться на новости</span>
</label>
<div className="actions">
<button className="button" type="submit" disabled={!canSubmit}>Отправить</button>
</div>
</form>
{submitted && (
<section className="result" aria-label="result">
<p><strong>Отправлено:</strong></p>
<p>Имя: {submitted.name}</p>
<p>Email: {submitted.email}</p>
<p>Сообщение: {submitted.message}</p>
<p>Подписка: {submitted.subscribe ? 'Да' : 'Нет'}</p>
</section>
)}
</article>
);
}
export default function App() {
return (
<main className="challenge-container">
<section>
<FeedbackForm />
</section>
</main>
);
}Соберите управляемую форму с несколькими полями и чекбоксом. При отправке покажите собранные данные и очистите форму.
Бизнес-кейс. LeadCapture — мини-форма лида: имя, email, сообщение и согласие на рассылку.
onChange.onSubmit соберите объект данных и отобразите его ниже.Карточка с полями формы, чекбоксом, кнопкой отправки и блоком «Отправлено».
Превью:

const [name, setName] = useState('') и аналогично для остальных.disabled={!name.trim() || !email.trim()}.onSubmit: e.preventDefault(); собрать { name, email, message, subscribe }, показать, затем очистить поля.canSubmit в переменную для читабельности.import React, { useState } from 'react';
import './styles.css';
export function FeedbackForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const [subscribe, setSubscribe] = useState(false);
const [submitted, setSubmitted] = useState(null);
function handleSubmit(e) {
e.preventDefault();
const canSubmit = name.trim() && email.trim();
if (!canSubmit) return;
setSubmitted({ name, email, message, subscribe });
setName('');
setEmail('');
setMessage('');
setSubscribe(false);
}
const canSubmit = name.trim() && email.trim();
return (
<article className="card" data-testid="form-card">
<header>
<h2 className="title">LeadCapture: форма обратной связи</h2>
<p className="subtitle">Управляемые поля + чекбокс, отправка формы</p>
</header>
<form className="row" onSubmit={handleSubmit} aria-label="form">
<input
className="input"
type="text"
placeholder="Имя"
value={name}
onChange={(e) => setName(e.target.value)}
aria-label="name"
/>
<input
className="input"
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
aria-label="email"
/>
<textarea
className="textarea"
placeholder="Сообщение"
value={message}
onChange={(e) => setMessage(e.target.value)}
aria-label="message"
rows={3}
/>
<label className="checkbox-row">
<input
className="checkbox"
type="checkbox"
checked={subscribe}
onChange={(e) => setSubscribe(e.target.checked)}
aria-label="subscribe"
/>
<span>Подписаться на новости</span>
</label>
<div className="actions">
<button className="button" type="submit" disabled={!canSubmit}>Отправить</button>
</div>
</form>
{submitted && (
<section className="result" aria-label="result">
<p><strong>Отправлено:</strong></p>
<p>Имя: {submitted.name}</p>
<p>Email: {submitted.email}</p>
<p>Сообщение: {submitted.message}</p>
<p>Подписка: {submitted.subscribe ? 'Да' : 'Нет'}</p>
</section>
)}
</article>
);
}
export default function App() {
return (
<main className="challenge-container">
<section>
<FeedbackForm />
</section>
</main>
);
}Редактор кода намеренно скрыт на мобильном.
Поверь, так лучше: я оберегаю тебя от искушения писать код в неидеальных условиях. Маленький экран и виртуальная клавиатура — не лучшие помощники для программиста.
📖 Сейчас: Изучи задачу, продумай решение. Действуй как стратег.
💻 Потом: Сядь за компьютер, открой сайт и реализуй все идеи с комфортом. Действуй как код-джедай!