Mantén el estado en el ancestro común y convierte tus widgets hijos en widgets controlados que informan de los cambios mediante callbacks.
Abrir esta lección en KodokonUna situación clásica: un selector de cantidad y un total mostrado en otro lugar necesitan compartir los mismos datos. La regla de oro: el estado vive en el ancestro común más cercano de los widgets que dependen de él. El padre posee los datos, los transmite como un parámetro y recibe los cambios mediante un callback que fluye de vuelta hacia arriba. Esto es "elevar el estado" (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('Cart')),
body: Column(
children: [
QuantitySelector(
quantity: _quantity,
onChanged: _updateQuantity,
),
Text('Total: ${_quantity * 20} €'),
],
),
);
}
}El hijo se convierte en un widget controlado: es un StatelessWidget, no almacena nada, muestra el valor que recibe y señala cada intención mediante onChanged. ValueChanged<int> es simplemente un alias de void Function(int). Fíjate en el botón de menos desactivado en la cantidad 1: basta con pasar null a onPressed, y esta lógica se deriva directamente del valor recibido.
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),
),
],
);
}
}Usas este contrato todo el tiempo sin darte cuenta: Checkbox, Slider, Switch son todos widgets controlados (value + onChanged). Cuando el árbol se hace más profundo y pasar los callbacks a través de cinco niveles se vuelve tedioso, será el momento de descubrir las soluciones de gestión de estado: ese es el tema del próximo módulo.