Understanding Flutter Keys: When and Why to Use Them
Understanding Flutter Keys: When and Why to Use Them
What You’ll Learn
Keys are Flutter’s way of preserving state when widgets move around in the widget tree. Most of the time, you don’t need them. But when you do, they’re essential for preventing bugs and unexpected behavior.
Keys tell Flutter how to match old widgets with new widgets during rebuilds. Without proper keys, Flutter might reuse state incorrectly, leading to UI glitches.
When Do You Need Keys?
You need keys when:
- Reordering a list of stateful widgets
- Adding or removing widgets from a collection
- Changing the type of widget at a specific position
Example: The Problem Without Keys
class ItemList extends StatefulWidget {
@override
_ItemListState createState() => _ItemListState();
}
class _ItemListState extends State<ItemList> {
List<Widget> items = [
ColoredBox(color: Colors.red),
ColoredBox(color: Colors.blue),
ColoredBox(color: Colors.green),
];
@override
Widget build(BuildContext context) {
return Column(
children: [
...items,
ElevatedButton(
onPressed: () {
setState(() {
// Remove first item
items.removeAt(0);
});
},
child: Text('Remove First'),
),
],
);
}
}
class ColoredBox extends StatefulWidget {
final Color color;
ColoredBox({required this.color});
@override
_ColoredBoxState createState() => _ColoredBoxState();
}
class _ColoredBoxState extends State<ColoredBox> {
late Color displayColor;
@override
void initState() {
super.initState();
displayColor = widget.color;
}
@override
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
color: displayColor,
);
}
}
When you remove the first item, you might see unexpected colors because Flutter reuses state incorrectly.
Solution: Adding Keys
class _ItemListState extends State<ItemList> {
List<Widget> items = [
ColoredBox(key: UniqueKey(), color: Colors.red),
ColoredBox(key: UniqueKey(), color: Colors.blue),
ColoredBox(key: UniqueKey(), color: Colors.green),
];
// ... rest stays the same
}
Types of Keys
ValueKey: Use when widgets can be uniquely identified by a value (like an ID)
ValueKey(item.id)
ObjectKey: Use when you have a unique object
ObjectKey(myObject)
UniqueKey: Creates a unique key each time (use sparingly)
UniqueKey()
GlobalKey: Use when you need to access widget state or context from anywhere (rare use case)
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Try It Yourself
Create a simple todo list where items can be reordered. First build it without keys and observe the behavior. Then add ValueKeys using the todo item’s text or ID. Notice how state preservation changes.
Tip of the Day
Use ValueKey with stable identifiers (like database IDs) rather than UniqueKey for list items. UniqueKey creates a new key on every rebuild, which defeats the purpose. For most list cases, ValueKey(item.id) is your best choice.