⚑ reactivity

Logo

A minimal and elegant state management solution for Flutter
Rebuild only what matters β€” with zero boilerplate.

βœ… Built for performance
🧠 Easy to learn
🎯 Flutter-native
πŸ’™ Perfect for UI-driven apps


🧨 The Power of ValueState + Named Records

The core feature of reactivity is seamless support for Dart Records via ValueState.

With ValueState, you manage multiple pieces of state β€” like name, age, isAdmin β€” using a single named record, with full type safety and zero boilerplate.

🀯 Example: Clean and Reactive

final user = ValueState<({String name, int age, bool isAdmin})>();

ReactiveState(user.on(
  (u) => Text('Name: ${u.name}, Age: ${u.age}, Admin: ${u.isAdmin}'),
));

user.refreshWith((name: 'Felipe', age: 30, isAdmin: true));

βœ” No classes
βœ” Fully typed
βœ” Instantly reactive
βœ” Native Dart syntax

If you love Dart’s record syntax, this will feel like magic.


✨ Features Overview

  • πŸ”„ refresh() β€” global rebuild trigger
  • 🧩 Reactive, ReactiveState, ReactiveStatus, ReactiveShow β€” declarative reactive widgets
  • 🧱 ValueState, InitedState, VoidState β€” flexible state containers
  • 🚦 refreshStatus() β€” reactive flow using enums
  • ❓ ReactiveNullable, ReactiveNullableList β€” handle nulls & empty states gracefully

πŸš€ Getting Started

Add the dependency:

dependencies:
  reactivity: ^1.0.0

Import it in your Dart file:

import 'package:reactivity/reactivity.dart';

βš™ Usage Examples

Global rebuild

int counter = 0;

Reactive(() => Text('Counter: $counter'));

counter++;
refresh(); // Triggers rebuild

Rebuild by key

final myKey = ReactiveKey();

Reactive(() => Text("Hello"), reactiveKey: myKey);

refreshOnly(myKey); // Rebuild just this one

🧱 State Containers

InitedState

final name = InitedState<String>("Kaian");

ReactiveState(name.on((value) => Text("Hello $value")));

name.refreshWith("Felipe");

ValueState

final count = ValueState<int>();

ReactiveState(count.on((value) => Text('Count: $value')));

count.refreshWith(1);
count.refreshUpdate((value) => value! + 1);

VoidState

final trigger = VoidState();

ReactiveState(trigger.on(() => Text("Triggered!")));

trigger.refresh();

🚦 ReactiveStatus

enum Status { loading, success, error }

refreshStatus(Status.loading);

ReactiveStatus<Status>(
  cases: {
    Status.loading: () => CircularProgressIndicator(),
    Status.success: () => Text("Done!"),
    Status.error: () => Text("Oops"),
  },
  defaultCase: () => Text("Idle"),
);

🎭 Conditional Rendering

ReactiveShow

bool isLogged = false;

ReactiveShow(
  showIf: () => isLogged,
  builder: () => Text("Welcome"),
  elseShow: Text("Login required"),
);

isLogged = true;
refresh();

ReactiveNullable

String? username;

ReactiveNullable<String>(
  value: username,
  builder: (name) => Text("Hi $name"),
  ifNull: Text("No user"),
);

username = "Felipe";
refresh();

ReactiveNullableList

List<String>? items;

ReactiveNullableList<String>(
  values: items,
  builder: (list) => ListView(children: list.map(Text.new).toList()),
  ifNull: CircularProgressIndicator(),
  ifEmpty: Text("No items"),
);

βœ… Why reactivity?

  • 🌟 First-class support for Dart Named Records
  • 🚫 No context, no classes, no scope hassles
  • 🧼 Clean and minimal API
  • πŸ’¬ Declarative, expressive, and beautiful
  • 🎯 Native to the Flutter widget tree

🀝 Contributing

Got ideas or found bugs?
Feel free to open issues or submit a pull request. Let's build this together!


πŸ“„ License

MIT License Β© Felipe Kaian