Flutter Daily: Understanding Keys and When to Use Them
Understanding Keys and When to Use Them
What You’ll Learn
Keys are Flutter’s way of preserving widget state when the widget tree changes. Most of the time you don’t need them, but when you do, they’re essential for preventing confusing bugs.
Why Keys Matter
When Flutter rebuilds the widget tree, it uses widget types and positions to determine which widgets changed. But sometimes widgets of the same type swap positions—like when you reorder a list. Without keys, Flutter might lose track of which widget is which, causing state to attach to the wrong widget.
Example: The Problem Without Keys
class ReorderableList extends StatefulWidget {
@override
_ReorderableListState createState() => _ReorderableListState();
}
class _ReorderableListState extends State<ReorderableList> {
List<String> items = ['Apple', 'Banana', 'Cherry'];
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return StatefulTile(text: items[index]);
},
);
}
}
class StatefulTile extends StatefulWidget {
final String text;
const StatefulTile({required this.text});
@override
_StatefulTileState createState() => _StatefulTileState();
}
class _StatefulTileState extends State<StatefulTile> {
bool isChecked = false;
@override
Widget build(BuildContext context) {
return CheckboxListTile(
title: Text(widget.text),
value: isChecked,
onChanged: (val) => setState(() => isChecked = val ?? false),
);
}
}
The Bug: If you check “Apple” and then remove it from the list, “Banana” might appear checked instead. Flutter reuses the widget state for the widget in position 0, not the widget with the “Apple” data.
The Solution: Add Keys
itemBuilder: (context, index) {
return StatefulTile(
key: ValueKey(items[index]), // Add this!
text: items[index],
);
}
Now Flutter tracks each tile by its content value, not just its position.
Types of Keys
ValueKey: Use when each widget has a unique data value
key: ValueKey(user.id)
ObjectKey: Use when you have a unique object
key: ObjectKey(product)
UniqueKey: Creates a key that’s never equal to another (rarely needed)
key: UniqueKey()
GlobalKey: Gives access to widget state from anywhere (use sparingly!)
final _formKey = GlobalKey<FormState>();
// Later: _formKey.currentState?.validate()
Try It Yourself
Create a simple to-do list where you can:
- Add items with a checkbox
- Remove items by tapping a delete icon
- Notice the state bug without keys
- Fix it by adding ValueKey with the item text
Pay attention to what happens to checkbox state when you delete items with and without keys.
Tip of the Day
When to use keys: You need keys when you have a list of stateful widgets that can be reordered, inserted, or removed. For stateless widgets or widgets that never change order, you can skip keys. If you see state “jumping” to the wrong widget, that’s your sign to add keys!