State, Events and Forms
State
State is data that changes over time and should update the UI when it does.
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Clicked {count} times
</button>
);
}
- Calling the setter re-renders the component with the new value.
- Use the function form
setCount(c => c + 1)when the new value depends on the old one. - Never mutate state directly:
items.push(x)does not re-render. Create new arrays and objects:setItems([...items, x]).
Controlled forms
function ContactForm({ onSubmit }) {
const [form, setForm] = useState({ name: "", email: "", message: "" });
const [error, setError] = useState("");
const update = e => setForm({ ...form, [e.target.name]: e.target.value });
function handleSubmit(e) {
e.preventDefault();
if (form.message.length < 20) return setError("Please add more detail.");
setError("");
onSubmit(form);
}
return (
<form onSubmit={handleSubmit} noValidate>
<label>Name <input name="name" value={form.name} onChange={update} required /></label>
<label>Email <input name="email" type="email" value={form.email} onChange={update} required /></label>
<label>Message <textarea name="message" value={form.message} onChange={update} /></label>
{error && <p role="alert">{error}</p>}
<button>Send</button>
</form>
);
}
The input's value always comes from state, so validation and formatting are easy.
Lifting state up
When two components need the same data, keep the state in their closest common parent and pass it down as props, with callbacks to change it:
function Shop() {
const [cart, setCart] = useState([]);
const add = product => setCart(c => [...c, product]);
return (<><ProductList onAdd={add} /><CartSummary items={cart} /></>);
}
Derived values
Do not store what you can calculate:
const total = cart.reduce((sum, p) => sum + p.cents, 0); // computed on each render
Duplicate state gets out of sync; derived values cannot.
Exercise
Build a filterable project list: a search input and category buttons in state; the visible list is derived with filter; a counter shows "N projects found".
Check yourself
- Why does
items.push(x)fail to update the UI? - What is a controlled input?
- Why calculate totals instead of storing them in state?
يُحفظ تقدّمك في هذا المتصفح فقط.
إرسال للمراجعة (10 نقطة)