Faites vivre l'état dans l'ancêtre commun et transformez vos widgets enfants en widgets contrôlés qui remontent les changements par callbacks.
Ouvrir cette leçon dans KodokonSituation classique : un sélecteur de quantité et un total affiché ailleurs doivent partager la même donnée. La règle d'or : l'état vit dans l'ancêtre commun le plus proche des widgets qui en dépendent. Le parent détient la donnée, la passe en paramètre vers le bas, et reçoit les changements par un callback qui remonte. C'est le « lifting state up ».
import 'package:flutter/material.dart';
class CartScreen extends StatefulWidget {
const CartScreen({super.key});
@override
State<CartScreen> createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen> {
int _quantity = 1;
void _updateQuantity(int value) {
setState(() => _quantity = value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Panier')),
body: Column(
children: [
QuantitySelector(
quantity: _quantity,
onChanged: _updateQuantity,
),
Text('Total : ${_quantity * 20} €'),
],
),
);
}
}L'enfant devient un widget contrôlé : il est StatelessWidget, ne stocke rien, affiche la valeur reçue et signale chaque intention via onChanged. ValueChanged<int> est simplement un alias de void Function(int). Remarquez le bouton moins désactivé sous la quantité 1 : passer null à onPressed suffit, et cette logique découle de la valeur reçue.
import 'package:flutter/material.dart';
class QuantitySelector extends StatelessWidget {
const QuantitySelector({
super.key,
required this.quantity,
required this.onChanged,
});
final int quantity;
final ValueChanged<int> onChanged;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.remove),
onPressed: quantity > 1
? () => onChanged(quantity - 1)
: null,
),
Text('$quantity'),
IconButton(
icon: const Icon(Icons.add),
onPressed: () => onChanged(quantity + 1),
),
],
);
}
}Vous utilisez ce contrat en permanence sans le savoir : Checkbox, Slider, Switch sont tous des widgets contrôlés (value + onChanged). Quand l'arbre se creuse et que faire transiter les callbacks sur cinq niveaux devient pénible, il sera temps de découvrir les solutions de gestion d'état - c'est l'objet du module suivant.