update abstract method
Handles a message and returns the new model state and optional command.
This is the heart of the Elm Architecture. When a message arrives (from user input, timers, async operations, etc.), this method:
- Examines the message
- Computes the new model state
- Optionally returns a command to execute
The returned tuple contains:
- The new model (can be
thisif unchanged) - An optional command to execute (or
null)
Pattern Matching
Dart's pattern matching makes update functions clean and readable:
@override
(Model, Cmd?) update(Msg msg) {
return switch (msg) {
// Match key type
KeyMsg(key: Key(type: KeyType.enter)) =>
(submitForm(), null),
// Match specific character
KeyMsg(key: Key(type: KeyType.runes, runes: [0x71])) =>
(this, Cmd.quit()),
// Match with modifier
KeyMsg(key: Key(ctrl: true, runes: [0x73])) => // Ctrl+S
(this, saveFile()),
// Match custom message with destructuring
DataLoadedMsg(:final items) =>
(copyWith(items: items, loading: false), null),
// Match window resize
WindowSizeMsg(:final width, :final height) =>
(copyWith(width: width, height: height), null),
// Default case - no change
_ => (this, null),
};
}
Immutability
Models should be immutable. Create new instances rather than modifying existing ones:
// ✓ Good - create new instance
return (CounterModel(count + 1), null);
// ✓ Good - use copyWith pattern
return (copyWith(count: count + 1), null);
// ✗ Bad - mutating state
count++;
return (this, null);
Implementation
(Model, Cmd?) update(Msg msg);