| Contrôlé | Non-contrôlé | |
|---|---|---|
| Valeur gérée par | React (state) | Le DOM |
| Accès à la valeur | Via le state | Via useRef |
| Recommandé ? | ✅ Oui | Cas spécifiques |
En React, on préfère les composants contrôlés : la valeur de l'input est liée au state.
function MonInput() {
const [valeur, setValeur] = useState('');
return (
<input
type="text"
value={valeur} // React contrôle la valeur
onChange={(e) => setValeur(e.target.value)} // Met à jour le state
/>
);
}
onChange se déclenche avec e.target.value.setValeur() met à jour le state.const [nom, setNom] = useState('');
const [age, setAge] = useState(0);
<input type="text" value={nom} onChange={e => setNom(e.target.value)} />
<input type="number" value={age} onChange={e => setAge(Number(e.target.value))} />
const [bio, setBio] = useState('');
// En React, textarea utilise value (pas de contenu entre les balises)
<textarea value={bio} onChange={e => setBio(e.target.value)} />
const [pays, setPays] = useState('fr');
<select value={pays} onChange={e => setPays(e.target.value)}>
<option value="fr">France</option>
<option value="be">Belgique</option>
<option value="ch">Suisse</option>
</select>
const [accepte, setAccepte] = useState(false);
<label>
<input
type="checkbox"
checked={accepte} // checked, pas value
onChange={e => setAccepte(e.target.checked)} // checked, pas value
/>
J'accepte les conditions
</label>
const [genre, setGenre] = useState('');
<label>
<input type="radio" value="homme" checked={genre === 'homme'}
onChange={e => setGenre(e.target.value)} /> Homme
</label>
<label>
<input type="radio" value="femme" checked={genre === 'femme'}
onChange={e => setGenre(e.target.value)} /> Femme
</label>
Au lieu d'un useState par champ, on peut utiliser un objet :
function Inscription() {
const [form, setForm] = useState({
nom: '',
email: '',
password: '',
pays: 'fr'
});
// Un seul handler pour tous les champs
const handleChange = (e) => {
const { name, value } = e.target;
setForm(prev => ({ ...prev, [name]: value }));
// ^^^^^^^^^
// propriété calculée (computed property)
};
return (
<form>
<input name="nom" value={form.nom} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<input name="password" type="password" value={form.password} onChange={handleChange} />
</form>
);
}
name de l'input correspond à la clé dans l'objet state. [name]: value utilise une propriété calculée pour mettre à jour la bonne clé.
function FormAvecValidation() {
const [email, setEmail] = useState('');
const [erreurs, setErreurs] = useState({});
const valider = () => {
const newErreurs = {};
if (!email) newErreurs.email = 'Email requis';
else if (!email.includes('@')) newErreurs.email = 'Email invalide';
return newErreurs;
};
const handleSubmit = (e) => {
e.preventDefault();
const err = valider();
setErreurs(err);
if (Object.keys(err).length === 0) {
alert('Formulaire valide !');
}
};
// ...
}
▼ Formulaire complet avec validation en temps réel
value={state} + onChange={handler}.checked + e.target.checked.checked={state === value}.value sur le <select>, pas sur <option>.[name]: value.e.preventDefault() sur onSubmit pour empêcher le rechargement.