reactive_orm

Pub Version | License: MIT

⚠️ Note: reactive_orm stands for a Reactive Object–Relationship Model.
It is not a database ORM.
It is a lightweight, field-level state management solution for Flutter UI, inspired by ORM-style modeling of objects and relationships β€” fully in-memory and UI-focused.


🎬 Demo

Reactive_ORM Demo


✨ Core Philosophy

  • Models are plain Dart objects
  • State changes happen via normal field mutation
  • UI reacts automatically, with optional field-specific reactivity
  • No ChangeNotifier, providers, streams, or extra boilerplate
  • Supports object-wise, field-wise, and nested reactivity
  • ORM-inspired design:
    • Objects represent application state
    • Relationships define propagation (Many β†’ One, Many ↔ Many)
    • Reactivity keeps the UI in sync

✨ Features

  • βœ… Reactive models with automatic UI updates
  • βœ… Object-wise reactivity (entire model rebuilds)
  • βœ… Field-wise reactivity (only selected fields rebuild)
  • βœ… Nested & shared models supported
  • βœ… Many β†’ One and Many ↔ Many relationships
  • βœ… Multiple widgets can listen to the same model
  • βœ… Minimal boilerplate
  • βœ… ORM-style mental model (Objects + Relationships)

πŸ†š Comparison

Feature setState Redux ValueNotifier Provider / ChangeNotifier BLoC Riverpod MobX reactive_orm
Plain Dart models ⚠️ Widget-bound ❌ Reducer-driven ⚠️ Wrapped value ❌ Extends notifier ❌ State classes ❌ Provider-based ⚠️ Annotated βœ… Plain Dart objects
Direct field mutation ⚠️ Inside widget ❌ ⚠️ value = x ❌ ❌ ❌ ⚠️ Observables βœ… model.field = value
Automatic UI updates ⚠️ Manual call βœ… βœ… βœ… βœ… βœ… βœ… βœ…
Field-wise reactivity ❌ ❌ ❌ ❌ Object-level ❌ ❌ βœ… βœ… Field-wise + object-wise
Multiple widgets listening ❌ βœ… Manual wiring Manual wiring Stream subscriptions Provider wiring Automatic Automatic
Nested models ❌ ❌ Manual ⚠️ Manual ❌ ⚠️ Manual ⚠️ Manual βœ… Built-in
Relationship support ❌ ❌ ❌ ❌ ❌ ❌ ❌ βœ… Many β†’ One, Many ↔ Many
Boilerplate Very Low Very High Medium Medium High Medium Medium Minimal, ORM-style
Async-first design ❌ ⚠️ Middleware ❌ ⚠️ Optional βœ… βœ… ⚠️ Optional ❌
Immutability required ❌ βœ… ❌ ❌ βœ… βœ… ❌ ❌
Mental model Widget-local state Global immutable store Single reactive value Observable objects Event β†’ State streams Immutable containers Observable variables Live object graph (ORM-style)
Ideal for Tiny local state Large predictable apps Simple values Small–medium apps Async-heavy logic Predictable state Explicit reactivity Complex reactive domain models

In More Brief --------------

Provider vs reactive_orm

Feature Provider / ChangeNotifier reactive_orm
Plain Dart models ❌ Extends ChangeNotifier βœ… Plain Dart objects
Field assignment syntax setX(); notifyListeners() model.field = newValue
Automatic UI updates βœ… βœ…
Field-wise reactivity ❌ Object-level only βœ… Field-wise + object-wise
Multiple widgets listening Manual provider wiring Automatic
Nested models ⚠️ Manual propagation βœ… Built-in
Relationships ❌ βœ… Many β†’ One, Many ↔ Many
Boilerplate Medium Minimal, ORM-style
Ideal for Small–medium apps Complex reactive domain models

BLoC vs reactive_orm

Feature BLoC reactive_orm
State update style Events β†’ Streams β†’ State Direct field mutation
Immutability Required Optional / mutable
Boilerplate High Minimal
Field-wise reactivity ❌ βœ…
Nested models ❌ βœ…
Relationships ❌ βœ… Many β†’ One, Many ↔ Many
Async-first design βœ… ❌
Mental model Event-driven ORM-style object graph
Ideal for Complex async flows Domain-driven UI state

Riverpod vs reactive_orm

Feature Riverpod reactive_orm
State model Immutable snapshots Live mutable objects
Update syntax state = state.copyWith() model.field = newValue
Field-wise reactivity ❌ βœ…
Nested models ⚠️ Manual βœ… Built-in
Relationships ❌ βœ… Many β†’ One, Many ↔ Many
Boilerplate Medium Minimal
Compile-time safety βœ… Strong ⚠️ Runtime
Ideal for Predictable state flows Relational domain models

MobX vs reactive_orm

Feature MobX reactive_orm
Reactivity declaration Annotations + codegen Automatic
Field-wise reactivity βœ… βœ…
Plain Dart models ⚠️ Annotated βœ… Plain Dart
Boilerplate Medium Minimal
Nested models ⚠️ Manual βœ… Built-in
Relationships ❌ βœ… Many β†’ One, Many ↔ Many
Tooling required Code generation None
Ideal for Explicit reactive fields ORM-style reactive objects

πŸš€ Getting Started

Installation

dependencies:
  reactive_orm: <latest_version>


🧩 Basic Usage

1️⃣ Create a Reactive Model

import 'package:reactive_orm/reactive_orm.dart';

class Task extends ReactiveModel {
  String _title;
  bool _completed = false;
  String _status = "Idle";

  Task({required String title}) : _title = title;

  String get title => _title;
  set title(String value) {
    if (_title != value) {
      _title = value;
      notifyListeners('title');
    }
  }

  bool get completed => _completed;
  set completed(bool value) {
    if (_completed != value) {
      _completed = value;
      notifyListeners('completed');
    }
  }

  String get status => _status;
  set status(String value) {
    if (_status != value) {
      _status = value;
      notifyListeners('status');
    }
  }
}

2️⃣ Object-wise Reactivity (Whole Object)

Any field change rebuilds the widget:

final task = Task(title: "Object-wise");

ReactiveBuilder<Task>(
  model: task,
  builder: (t) => ListTile(
    title: Text(t.title),
    subtitle: Text(t.status),
    trailing: Checkbox(
      value: t.completed,
      onChanged: (v) => t.completed = v!,
    ),
  ),
);

3️⃣ Field-wise Reactivity (Optimized)

Widget rebuilds only when specified fields change:

final task = Task(title: "Field-wise");

ReactiveBuilder<Task>(
  model: task,
  fields: ['completed', 'status'],
  builder: (t) => ListTile(
    title: Text(t.title),
    subtitle: Text(t.status),
    trailing: Checkbox(
      value: t.completed,
      onChanged: (v) => t.completed = v!,
    ),
  ),
);
  • Rebuilds only when completed or status changes.
  • Changes to other fields are ignored.

πŸ”— Relationship Patterns

1-> Many β†’ One (Aggregation)

Multiple models feed a single reactive observer:

class Dashboard extends ReactiveModel {
  final List<Task> sources;
  Dashboard(this.sources) {
    for (final task in sources) addNested(task);
  }
}

final dashboard = Dashboard([task1, task2]);

ReactiveBuilder<Dashboard>(
  model: dashboard,
  builder: (_) => Text("Dashboard updated"),
);
  • βœ” Any task change updates the dashboard automatically.

2-> Many ↔ Many (Shared Models)

Same model instance used across multiple parents:

class Group extends ReactiveModel {
  final String name;
  final List<Task> tasks;

  Group({required this.name, required this.tasks}) {
    for (final task in tasks) addNested(task);
  }
}
  • βœ” One task update reflects everywhere.
  • βœ” No duplication or manual syncing required.

🧠 How It Works (High Level)

  • Models extend ReactiveModel.
  • Field setters call notifyListeners(fieldName) when the value changes.
  • ReactiveBuilder widgets listen to either:
    • Whole model (object-wise)
    • Specific fields (field-wise)
  • Nested models propagate changes upward automatically.
  • Widgets rebuild safely, respecting Flutter lifecycle.

πŸ›£ Roadmap

  • Batch updates / transactions
  • Async persistence hooks
  • Database adapters (optional)
  • DevTools / debug inspector
  • Optional code generation

πŸ§ͺ Status

  • Version: 0.0.7
  • Stability: Stable (suitable for prototyping and early production)
  • Focus: Reactive domain models & scalable state management

πŸ“Œ Summary

reactive_orm is ideal when you want:

  • Clean Dart models with fine-grained reactivity
  • A Reactive Object–Relationship Model for UI state
  • Object-wise and field-wise rebuild control
  • Nested and shared models without manual wiring
  • Minimal boilerplate with a clear mental model
  • A lightweight yet scalable state management solution for Flutter apps

Libraries

reactive_orm