← Flutter & Dart

Fundamentos de Flutter

¿Cuál es la diferencia entre un `StatelessWidget` y un `StatefulWidget`, y cuándo usar cada uno?

Ver respuesta — intenta responderla en voz alta primero

Un StatelessWidget no tiene estado interno que cambie: se dibuja una vez con la información que recibe y no se redibuja por sí mismo. Un StatefulWidget mantiene un estado mutable que puede cambiar durante la vida del widget; cuando ese estado cambia (con setState), Flutter lo reconstruye. Usa stateful solo cuando el widget necesita cambiar por sí mismo.

  • StatelessWidget: pura descripción. Todo lo que necesita llega por su constructor (sus parámetros). Si esos datos no cambian, el widget no cambia. Ejemplos: un ícono, una etiqueta de texto, un botón que solo muestra algo.
  • StatefulWidget: tiene una clase State asociada donde vive información que puede cambiar: un contador, si un switch está encendido, el texto de un campo. Cuando llamas a setState(), Flutter vuelve a ejecutar build y actualiza la UI.

Regla práctica: empieza siempre con StatelessWidget. Solo pásate a StatefulWidget cuando el widget necesite recordar algo que cambia con el tiempo y que él mismo controla.

import 'package:flutter/material.dart';

// Stateless: solo muestra lo que recibe
class Saludo extends StatelessWidget {
  final String nombre;
  const Saludo({super.key, required this.nombre});

  @override
  Widget build(BuildContext context) {
    return Text("Hola, $nombre");
  }
}

// Stateful: mantiene un contador que cambia
class Contador extends StatefulWidget {
  const Contador({super.key});

  @override
  State<Contador> createState() => _ContadorState();
}

class _ContadorState extends State<Contador> {
  int _cuenta = 0; // estado mutable

  void _incrementar() {
    setState(() {
      _cuenta++; // cambia el estado y pide reconstruir
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text("Cuenta: $_cuenta"),
        ElevatedButton(onPressed: _incrementar, child: const Text("+1")),
      ],
    );
  }
}

Usar StatefulWidget para todo "por si acaso". Un widget con estado es más pesado y más propenso a bugs (olvidar setState, no limpiar recursos en dispose). Si los datos solo llegan de afuera y no cambian dentro del widget, un StatelessWidget es más simple y eficiente. Otro error: modificar una variable de estado sin envolverla en setState, con lo cual la UI no se actualiza.

"Un StatelessWidget no tiene estado interno que cambie: se dibuja con lo que recibe por el constructor y no se redibuja solo. Un StatefulWidget tiene una clase State con datos mutables, y cuando llamo a setState Flutter reconstruye el widget para reflejar el cambio. Mi regla es empezar con stateless y solo usar stateful cuando el widget necesita recordar algo que cambia con el tiempo, como un contador o un formulario."

Reto rápido

Si cambias una variable de estado pero la UI no se actualiza, ¿cuál es la causa más probable?

Ver respuesta

Que modificaste la variable fuera de setState(). Cambiar _cuenta++ directamente actualiza el valor en memoria, pero no le avisa a Flutter que debe reconstruir. Hay que envolver el cambio: setState(() { _cuenta++; });. (En un StatelessWidget directamente no hay setState porque no está pensado para cambiar solo.)