What are Keys in Flutter and when should you use them?

High PriorityAsked in ~70% of Flutter interviews

3 min read

Flutter Internals

Theory — why keys matter

Flutter's diff algorithm compares old and new widget trees at each position. By default:

Before:  [A] [B] [C]                  After removing B:  [A] [C]
          ↑                                                ↑
         pos 0    1   2                                   pos 0   1

Without keys, Flutter sees "position 1 used to be B, now it's C" — it doesn't drop B, it rewrites it into C, keeping B's underlying State attached to the new widget. For stateless widgets that's harmless; for stateful ones (checkboxes, text fields, animations), state ends up on the wrong row.

With keys, Flutter matches by identity:

Before:  [A:1] [B:2] [C:3]            After:  [A:1] [C:3]

Now B is correctly disposed and C keeps its state.


The 4 key types

KeyIdentity is…Use for
ValueKey(x)== on the valueMost lists — pass a stable item id
ObjectKey(o)identity (identical) of the objectWhen values can be equal but instances differ
UniqueKey()unique every buildForce a widget to rebuild from scratch
GlobalKey<T>unique app-wideAccess a child's state or RenderObject from outside

Code in action

// 1️⃣ Stateful list items — keys preserve state on reorder/remove
ListView(
  children: users.map((u) => CheckboxTile(
    key: ValueKey(u.id),
    user: u,
  )).toList(),
);

// 2️⃣ Force a clean slate (reset a form when filters change)
RefreshableProductList(key: ValueKey(filter));   // new key → new state

// 3️⃣ Global key — read/control child state
final _formKey = GlobalKey<FormState>();
Form(key: _formKey, child: ...);
if (_formKey.currentState!.validate()) { ... }

// 4️⃣ UniqueKey — when you specifically want a remount
AnimatedSwitcher(
  child: Container(key: UniqueKey(), color: bgColor),
);

When to add a key

SituationKey?
List of stateless display items (Text)❌ Not needed
List of stateful items that can reorder/insert/removeValueKey(id)
Swapping between two widgets of the same type✅ Distinct keys to force a remount
Reading a child widget's state from outsideGlobalKey<T>
Forcing a remount when params changeValueKey(param)
Every widget "just to be safe"❌ Overhead with no benefit

Common mistakes to avoid

// ❌ No keys on stateful list items — state attaches to wrong row
Column(children: items.map((i) => CheckboxTile(item: i)).toList());

// ✅ Stable ValueKey
Column(children: items.map((i) => CheckboxTile(
  key: ValueKey(i.id),
  item: i,
)).toList());

// ❌ Using UniqueKey() in a hot path — forces full remount every build
return ListView(
  children: items.map((i) => Tile(key: UniqueKey(), item: i)).toList(),
);
// ✅ Use stable IDs unless you actually want a remount

// ❌ Using `i` (index) as the key in a reorderable list
key: ValueKey(index),   // shifts when you remove/reorder → defeats the purpose

// ❌ Over-using GlobalKey — they're more expensive and lifecycle-tricky
GlobalKey here, GlobalKey there → state lookups everywhere
// ✅ Prefer callbacks / lifting state; GlobalKey only when you truly need cross-tree access

// ❌ Putting a key on the wrong widget
// Keys go on the widget WHOSE IDENTITY matters across rebuilds —
// usually the top widget you return for each item, not the inner Text.

Interview follow-ups

  1. What's the difference between ValueKey and ObjectKey? ValueKey(v) uses == on the wrapped value — perfect for stable IDs. ObjectKey(o) uses identical() — useful when two model instances have equal fields but aren't the same object, and you want them treated as distinct.

  2. When does UniqueKey() actually make sense? When you want the widget to be torn down and recreated — e.g., resetting an AnimationController inside a child, or making AnimatedSwitcher treat two same-typed widgets as different.

  3. What does a GlobalKey do, and what are the trade-offs? It gives the widget a unique identity across the whole tree, so its element can move without being recreated, and you can read currentState / currentContext / currentWidget from anywhere. Trade-offs: more memory, gotchas around moving in/out of the tree, and easy to overuse.

  4. Why does using index as a key in a dynamic list break state preservation? Because the index shifts when items are added/removed/reordered. Item at index 2 might become index 1 after a delete — same key, different item, same broken matching you get with no key.


How helpful was this content?

Please sign in to rate this article.