← Flutter & Dart

Estado en Flutter

¿Qué hace `setState` y qué pasa exactamente cuando lo llamas?

Ver respuesta — intenta responderla en voz alta primero

setState le avisa a Flutter que el estado interno de un widget cambió y que debe reconstruirlo. Marca el elemento como "sucio" y agenda una nueva llamada a build en el siguiente frame. Debes poner el cambio de estado dentro del callback de setState, no fuera.

Cuando cambias una variable de estado, Flutter no lo detecta solo. setState(() { ... }) hace dos cosas:

  1. Ejecuta el código que le pasas (donde modificas el estado).
  2. Marca el widget como "necesita reconstruirse" para que Flutter llame a build de nuevo y actualice la pantalla.

Es la forma más básica de manejar estado en Flutter. Funciona genial para estado local de un widget (un contador, si un panel está abierto). Para estado que comparten muchos widgets, se queda corto y conviene usar una solución de gestión de estado.

import 'package:flutter/material.dart';

class Interruptor extends StatefulWidget {
  const Interruptor({super.key});
  @override
  State<Interruptor> createState() => _InterruptorState();
}

class _InterruptorState extends State<Interruptor> {
  bool _encendido = false;

  @override
  Widget build(BuildContext context) {
    return SwitchListTile(
      title: Text(_encendido ? "Encendido" : "Apagado"),
      value: _encendido,
      onChanged: (nuevo) {
        setState(() {
          _encendido = nuevo; // el cambio va DENTRO de setState
        });
      },
    );
  }
}

Dos errores frecuentes:

  1. Cambiar el estado fuera de setState: _encendido = true; sin envolverlo. El valor cambia pero la UI no se actualiza.
  2. Llamar setState durante build o después de que el widget se desmontó. Llamar setState tras un await sin verificar mounted puede lanzar "setState() called after dispose()". Solución: if (mounted) setState(...).

"setState le avisa a Flutter que el estado del widget cambió, marca el elemento como sucio y agenda una reconstrucción con build. El cambio de estado tiene que ir dentro del callback de setState, si no, la UI no se entera. Lo uso para estado local de un widget, como un contador o un switch. Para estado compartido entre muchos widgets prefiero una solución como Provider o Riverpod, porque setState solo reconstruye ese widget."

Reto rápido

¿Qué diferencia hay entre estas dos líneas dentro de un State?

_cuenta++;
setState(() => _cuenta++);
Ver respuesta

_cuenta++; cambia el valor en memoria pero no reconstruye la UI: la pantalla seguirá mostrando el número viejo hasta que otra cosa dispare un build. setState(() => _cuenta++); cambia el valor y le pide a Flutter que reconstruya, así que la pantalla se actualiza de inmediato.