reactive_orm
β οΈ Note:
reactive_ormstands 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

β¨ 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
completedorstatuschanges. - 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. ReactiveBuilderwidgets 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