# Dart Patterns You Will Use in Flutter — Dart

Source: https://www.skillbyai.com/en/dart/p-flutter

> Connect Dart language features to everyday Flutter code.

## The language inside the UI framework

Flutter code is Dart code, and several language features appear constantly. **Named parameters** with `required` define widget APIs (`Text('Hi', style: ...)`). **`const` constructors** let Flutter reuse widget instances and skip rebuilding them, so prefer `const` widgets wherever possible. **Immutable classes** with `final` fields and `copyWith` methods model state that changes by replacement rather than mutation, which state-management libraries (Provider, Riverpod, Bloc) rely on. **Sealed classes and switch expressions** model UI states (`Loading`, `Loaded`, `Failed`) with compile-time exhaustiveness. **Collection if/for and spread** build widget lists declaratively. **Futures and Streams** drive `FutureBuilder` and `StreamBuilder`, and `async` callbacks handle button taps. **`late`** fields are initialised in `initState`, and subscriptions and controllers must be cancelled or disposed in `dispose`. **Isolates** (`compute` or `Isolate.run`) keep heavy parsing off the UI thread so animations stay smooth. The existing Flutter course on this site covers widgets, layout and state management in depth.

## An immutable state model with copyWith and a sealed UI state

Typical Dart shapes in a Flutter app, independent of any state library.

```dart
class CartState {
  const CartState({this.items = const [], this.couponCode});
  final List<String> items;
  final String? couponCode;

  CartState copyWith({List<String>? items, String? couponCode}) => CartState(
        items: items ?? this.items,
        couponCode: couponCode ?? this.couponCode,
      );

  CartState addItem(String sku) => copyWith(items: [...items, sku]);   // new state, no mutation
}

sealed class ProductsState {}
class ProductsLoading extends ProductsState {}
class ProductsLoaded extends ProductsState {
  ProductsLoaded(this.titles);
  final List<String> titles;
}
class ProductsFailed extends ProductsState {
  ProductsFailed(this.message);
  final String message;
}

String render(ProductsState state) => switch (state) {   // in Flutter this would return widgets
      ProductsLoading() => 'Loading...',
      ProductsLoaded(:final titles) when titles.isEmpty => 'No products yet',
      ProductsLoaded(:final titles) => titles.join(', '),
      ProductsFailed(:final message) => 'Error: $message',
    };

void main() {
  const empty = CartState();
  final cart = empty.addItem('pen').addItem('ink');
  print('${empty.items.length} -> ${cart.items.length}');   // 0 -> 2
  print(render(ProductsLoaded(['Notebook', 'Pen'])));
}
```

## copyWith cannot clear a nullable field this way

With `couponCode ?? this.couponCode`, passing null keeps the old value, so you cannot remove a coupon. Packages such as `freezed` generate copyWith methods that distinguish "not passed" from "set to null".

**Quiz:** Why are const constructors valuable in Flutter widget trees?

- [x] Identical const widgets are canonicalised, so Flutter can reuse them and skip unnecessary rebuild work
- [ ] They make widgets mutable
- [ ] They enable hot reload
- [ ] They are required for every widget

*Answer:* Identical const widgets are canonicalised, so Flutter can reuse them and skip unnecessary rebuild work. const instances are created once and shared, reducing rebuild cost.
