Riverpod: Notifier
Parte de la sección Gestión del estado del Journey de Flutter de Coddy. Lección 19 de 27.
Un StateProvider es adecuado para un número. Cuando el estado tiene reglas, como una lista con métodos para añadir y eliminar elementos, escribe un Notifier: una clase que contiene el estado y los métodos que lo modifican.
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
void add(String name) {
state = [...state, name];
}
}
final guestsProvider =
NotifierProvider<GuestList, List<String>>(GuestList.new);build devuelve el estado inicial, una lista vacía. Dentro de la clase, state es el valor actual. GuestList.new es el constructor de la clase, que se entrega al proveedor para que pueda crear el notificador.
La regla clave: asigna un valor nuevo a state, nunca modifiques el anterior. Riverpod avisa a los widgets solo cuando state recibe un objeto diferente. state.add(name) modifica la lista directamente, así que state sigue siendo la misma lista y nadie se entera. [...state, name] crea una lista nueva: los tres puntos expanden en ella cada nombre anterior y después se añade el nuevo al final.
Un widget llama a un método a través del notificador: ref.read(guestsProvider.notifier).add('Ada'). Esta página es un ConsumerStatefulWidget, el tipo con estado, porque también mantiene un controlador de texto. Su State tiene ref como campo.
Desafío
DifícilLa lista de invitados muestra los nombres de guestsProvider, pero Add solo borra el campo.
- Agrega un método
add(String name)aGuestListque establezcastatecomo una lista nueva con el nombre al final. - Haz que
Addlo llame con el texto del campo antes de borrar el campo.
Pruébalo tú mismo
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
}
final guestsProvider = NotifierProvider<GuestList, List<String>>(GuestList.new);
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: PartyPage(),
);
}
}
class PartyPage extends ConsumerStatefulWidget {
const PartyPage({super.key});
@override
ConsumerState<PartyPage> createState() => _PartyPageState();
}
class _PartyPageState extends ConsumerState<PartyPage> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final guests = ref.watch(guestsProvider);
return Scaffold(
appBar: AppBar(title: Text('Guests: ${guests.length}')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Guest name'),
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
controller.clear();
},
child: const Text('Add'),
),
],
),
),
Expanded(
child: ListView(
children: [
for (final name in guests) ListTile(leading: const Icon(Icons.person), title: Text(name)),
],
),
),
],
),
);
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Gestión del estado
Practica por tu cuenta: Compilador de Flutter online