skills/flutter/references/features-keys.md

156 lines
3.0 KiB
Markdown

---
name: features-keys
description: Flutter keys - ValueKey, ObjectKey, GlobalKey, UniqueKey, and when to use keys
---
# Keys
Keys help Flutter identify which widgets correspond to which state objects.
## When to Use Keys
Use keys when widgets are moved around in the tree or when you need to preserve state.
```dart
// Without key - state is lost when list order changes
ListView(
children: items.map((item) => StatefulWidget()).toList(),
)
// With key - state is preserved
ListView(
children: items.map((item) =>
StatefulWidget(key: ValueKey(item.id))
).toList(),
)
```
## ValueKey
Use when widget identity is based on a value.
```dart
ListView(
children: items.map((item) =>
ListTile(
key: ValueKey(item.id),
title: Text(item.name),
)
).toList(),
)
```
## ObjectKey
Use when widget identity is based on object identity.
```dart
ListView(
children: items.map((item) =>
ListTile(
key: ObjectKey(item),
title: Text(item.name),
)
).toList(),
)
```
## UniqueKey
Generate a unique key each time (use sparingly).
```dart
// Creates new key on every build - not recommended
Widget build(BuildContext context) {
return Widget(key: UniqueKey());
}
// Better - create once in initState
@override
void initState() {
super.initState();
_key = UniqueKey();
}
```
## GlobalKey
Uniquely identify widgets across the entire app.
```dart
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: TextFormField(),
)
// Access form state from anywhere
_formKey.currentState?.validate();
```
## GlobalKey for State Access
```dart
final _counterKey = GlobalKey<_CounterWidgetState>();
CounterWidget(key: _counterKey)
// Access state
_counterKey.currentState?.increment();
```
## Key in AnimatedSwitcher
Use keys to force widget recreation.
```dart
AnimatedSwitcher(
duration: Duration(milliseconds: 300),
child: Text(
'$_counter',
key: ValueKey(_counter), // Force recreation on change
),
)
```
## Key Best Practices
```dart
// ✅ Good - use ValueKey for list items
ListView.builder(
itemBuilder: (context, index) => ListTile(
key: ValueKey(items[index].id),
title: Text(items[index].name),
),
)
// ✅ Good - use GlobalKey for form access
final _formKey = GlobalKey<FormState>();
// ❌ Bad - creating UniqueKey on every build
Widget build(BuildContext context) {
return Widget(key: UniqueKey());
}
// ✅ Good - create key once
final _key = UniqueKey();
```
## Key Points
- Use `ValueKey` for list items with stable IDs
- Use `ObjectKey` when identity is based on object reference
- Use `UniqueKey` sparingly, create once in initState
- Use `GlobalKey` to access state from outside
- Keys help preserve state when widgets move
- Keys help Flutter identify widgets efficiently
- Don't create keys unnecessarily
- Use keys in lists, AnimatedSwitcher, and when accessing state
<!--
Source references:
- https://github.com/flutter/flutter/tree/main/packages/flutter/lib/src/widgets/framework.dart
- https://docs.flutter.dev/development/ui/widgets-intro#keys
-->