Widgets stateful
Aprende sobre StatefulWidgets y cómo reconstruir la UI de Flutter.
Aprende cuándo los widgets necesitan ser stateful y cómo activar actualizaciones de la UI con setState.
Qué lograrás
Pasos
1
Introducción
Introducción
Hasta ahora, tu aplicación muestra una cuadrícula y un campo de entrada, pero la cuadrícula aún no se actualiza para reflejar los intentos del usuario. Cuando esta aplicación esté completa, cada casilla en la siguiente fila vacía debería actualizarse después de cada intento enviado por el usuario al:
- Mostrar la letra correcta.
- Cambiar de color para reflejar si la letra es correcta (verde), está en la palabra pero en una posición incorrecta (amarillo), o no aparece en la palabra en absoluto (gris).
Para manejar este comportamiento dinámico, necesitas convertir GamePage de un
StatelessWidget a un StatefulWidget.
2
¿Por qué widgets stateful?
¿Por qué widgets stateful?
Cuando la apariencia o los datos de un Widget necesitan cambiar durante su ciclo de vida,
necesitas un StatefulWidget y un objeto State
asociado.
Aunque el StatefulWidget en sí mismo sigue siendo inmutable (sus propiedades
no pueden cambiar después de su creación), el objeto State es de larga duración,
puede contener datos mutables y se puede reconstruir cuando esos datos cambian,
haciendo que la UI se actualice.
Por ejemplo, el siguiente árbol de widgets imagina una aplicación simple que utiliza un widget stateful con un contador que incrementa cuando se presiona el botón.
Aquí está la estructura básica de StatefulWidget (aún no hace nada):
class ExampleWidget extends StatefulWidget {
ExampleWidget({super.key});
@override
State<ExampleWidget> createState() => _ExampleWidgetState();
}
class _ExampleWidgetState extends State<ExampleWidget> {
@override
Widget build(BuildContext context) {
return Container();
}
}
3
Convierte GamePage a un widget stateful
Convierte GamePage a un widget stateful
Para convertir el widget GamePage (o cualquier otro) de
un widget stateless a un widget stateful, sigue estos pasos:
- Cambia
GamePagepara que extiendaStatefulWidgeten lugar deStatelessWidget. - Crea una nueva clase llamada
_GamePageState, que extiendaState<GamePage>. Esta nueva clase contendrá el estado mutable y el métodobuild. Mueve el métodobuildy todas las propiedades instanciadas en el widget desdeGamePageal objeto State. - Implementa el método
createState()enGamePage, el cual devuelve una instancia de_GamePageState.
Tu código modificado debería verse así:
class GamePage extends StatefulWidget {
GamePage({super.key});
@override
State<GamePage> createState() => _GamePageState();
}
class _GamePageState extends State<GamePage> {
final Game _game = Game();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
for (var guess in _game.guesses)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var letter in guess)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.5, vertical: 2.5),
child: Tile(letter.char, letter.type),
)
],
),
GuessInput(
onSubmitGuess: (_) {
// TODO, handle guess
print(guess); // Temporary
},
),
],
),
);
}
}
4
Actualizar la UI con setState
Actualizar la UI con setState
Cada vez que mutes un objeto State,
debes llamar a setState
para indicarle al framework que
actualice la interfaz de usuario y llame al método build nuevamente.
En esta aplicación, cuando un usuario hace un intento, la palabra que intentó se
guarda en el objeto Game, el cual es una propiedad de la clase GamePage
asociada,
y por lo tanto es un estado que podría cambiar y requerir que la UI se actualice.
Cuando este estado se muta, la cuadrícula debe
redibujarse para mostrar el intento del usuario.
Para implementar esto, actualiza la función callback pasada a GuessInput.
La función necesita llamar a setState y, dentro de setState,
necesita ejecutar la lógica para determinar si el intento del usuario fue correcto.
Actualiza tu código:
class GamePage extends StatefulWidget {
GamePage({super.key});
@override
State<GamePage> createState() => _GamePageState();
}
class _GamePageState extends State<GamePage> {
final Game _game = Game();
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
for (var guess in _game.guesses)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var letter in guess)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.5, vertical: 2.5),
child: Tile(letter.char, letter.type),
)
],
),
GuessInput(
onSubmitGuess: (String guess) {
setState(() { // NEW
_game.guess(guess);
});
},
),
],
),
);
}
}
Ahora, cuando escribas un intento válido en el TextInput y lo envíes,
la aplicación reflejará el intento del usuario.
Si llamaras a _game.guess(guess) sin llamar a
setState,
los datos internos del juego cambiarían, pero Flutter no sabría que
necesita redibujar la pantalla, y el usuario no vería ninguna actualización.
5
Revisión
Revisión
Qué lograste
Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.Aprendiste cuándo los widgets necesitan ser stateful
Cuando la apariencia o los datos de un Widget necesitan cambiar durante su ciclo de vida, necesitas un StatefulWidget. El Widget en sí permanece inmutable, pero su objeto
State asociado contiene datos mutables y activa reconstrucciones.
Convertiste GamePage a un StatefulWidget
Refactorizaste GamePage para que sea stateful creando una clase _GamePageState
asociada, moviendo el método build y las propiedades mutables a ella, e implementando createState(). El soporte de tu IDE para quick assists puede automatizar esta conversión.
Hiciste que tu aplicación responda a la entrada del usuario con setState
Llamar a setState le dice a Flutter que reconstruya la UI de un Widget. Cuando un usuario envía un intento, llamas a
setState para actualizar el estado del juego, y la cuadrícula refleja automáticamente los nuevos datos. ¡Tu aplicación ahora es verdaderamente interactiva!
6
Ponte a prueba
Ponte a prueba
Cuestionario sobre Widgets Stateful
1 / 2Cuando la apariencia o los datos del widget necesitan cambiar durante su ciclo de vida.
¡Así es!
Se necesita un StatefulWidget cuando la UI debe actualizarse en respuesta a cambios de datos a lo largo del tiempo.
Cuando el widget tiene más de tres widgets hijos.
No exactamente.
El número de hijos no determina si un widget es stateful.
Cuando el widget está en la raíz del árbol de widgets.
No exactamente.
Los widgets raíz pueden ser stateless; que sea stateful depende de si los datos cambian durante el ciclo de vida del widget.
Cuando el widget necesita realizar peticiones HTTP.
No exactamente.
Las peticiones HTTP se pueden realizar desde cualquiera de los dos, pero los cambios de estado requieren StatefulWidget.
La aplicación fallará con un error.
No exactamente.
La aplicación no fallará, pero la UI no se actualizará.
Flutter detecta automáticamente el cambio y reconstruye la UI.
No exactamente.
Flutter requiere setState para saber cuándo reconstruir; no detecta automáticamente los cambios.
El widget se elimina del árbol de widgets.
No exactamente.
El widget permanece; simplemente no se actualizará visualmente sin setState.
Los datos cambian internamente, pero Flutter no reconstruirá la UI para reflejar el cambio.
¡Así es!
Sin llamar a setState, Flutter no sabe que necesita redibujar, por lo que el usuario no verá las actualizaciones.
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-06-08. Ver código fuente oreportar un problema.