reactiv 1.0.1 copy "reactiv: ^1.0.1" to clipboard
reactiv: ^1.0.1 copied to clipboard

Production-ready reactive state management with robust logging, undo/redo, computed values, debounce/throttle, and more. Lightweight, powerful, and easy to use.

Reactiv #

Production-Ready Reactive State Management for Flutter

pub package CI License Stars

Lightweight • Powerful • Type-Safe • Production-Ready

Get StartedDocumentationExamplesFeatures


🚀 What is Reactiv? #

Reactiv is a production-ready reactive state management solution for Flutter that combines simplicity with powerful features. Built with developer experience in mind, it offers:

  • Zero boilerplate - Write less code, do more
  • Type-safe - Compile-time checks prevent runtime errors
  • Zero memory leaks - Smart dependency injection with automatic cleanup
  • Undo/Redo - Built-in history tracking
  • Computed values - Auto-updating derived state
  • Debounce/Throttle - Performance optimization built-in
  • 100% tested - Battle-tested in production apps

Why Choose Reactiv? #

Feature Reactiv GetX Provider Riverpod BLoC
Lines of Code ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Learning Curve ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Type Safety ⚠️
Dependency Injection ⚠️
Undo/Redo
Computed Values
Package Size ~150 APIs 2400+ APIs Medium Large Large

📦 Installation #

Add to your pubspec.yaml:

dependencies:
  reactiv: ^1.0.0

Then run:

flutter pub get

⚡ Quick Start #

1. Create a Controller #

import 'package:reactiv/reactiv.dart';

class CounterController extends ReactiveController {
  // Define reactive variables
  final count = ReactiveInt(0);
  
  // Add business logic
  void increment() => count.value++;
  void decrement() => count.value--;
}

2. Inject & Use #

class CounterScreen extends StatefulWidget {
  @override
  State<CounterScreen> createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  @override
  void initState() {
    super.initState();
    // Inject the controller
    Dependency.put(CounterController());
  }

  @override
  void dispose() {
    // Clean up
    Dependency.delete<CounterController>();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final controller = Dependency.find<CounterController>();
    
    return Scaffold(
      appBar: AppBar(title: const Text('Reactiv Counter')),
      body: Center(
        // Observer automatically rebuilds when count changes
        child: Observer(
          listenable: controller.count,
          listener: (count) => Text(
            'Count: $count',
            style: Theme.of(context).textTheme.headlineLarge,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: controller.increment,
        child: const Icon(Icons.add),
      ),
    );
  }
}

That's it! 🎉 You have a fully functional reactive counter with automatic memory management.


🌟 Key Features #

1️⃣ Undo/Redo Support (NEW in v1.0.0) #

final text = ReactiveString('Hello', enableHistory: true);

text.value = 'World';
text.value = 'Flutter';

text.undo(); // Back to 'World'
text.redo(); // Forward to 'Flutter'

print(text.canUndo); // true
print(text.canRedo); // false

2️⃣ Computed Values (NEW in v1.0.0) #

Auto-updating derived state:

final firstName = 'John'.reactiv;
final lastName = 'Doe'.reactiv;

final fullName = ComputedReactive(
  () => '${firstName.value} ${lastName.value}',
  dependencies: [firstName, lastName],
);

firstName.value = 'Jane';
// fullName automatically updates to 'Jane Doe'!

3️⃣ Debounce & Throttle (NEW in v1.0.0) #

Perfect for search inputs and scroll events:

// Debounce - wait for user to stop typing
final searchQuery = ReactiveString('');
searchQuery.setDebounce(Duration(milliseconds: 500));
searchQuery.updateDebounced('flutter'); // Waits 500ms

// Throttle - limit update frequency
final scrollPosition = ReactiveInt(0);
scrollPosition.setThrottle(Duration(milliseconds: 100));
scrollPosition.updateThrottled(150); // Max once per 100ms

4️⃣ Lazy Dependency Injection (NEW in v1.0.0) #

Controllers created only when needed:

// Register lazy builder - controller NOT created yet
Dependency.lazyPut(() => ExpensiveController());

// Controller created here, on first access
final controller = Dependency.find<ExpensiveController>();

5️⃣ Ever & Once Listeners (NEW in v1.0.0) #

// Called on every change
count.ever((value) => print('New value: $value'));

// Called only once, then auto-removed
count.once((value) => showWelcomeDialog());

6️⃣ Multiple Observer Support #

Observe multiple reactive variables:

Observer2(
  listenable: firstName,
  listenable2: lastName,
  listener: (first, last) => Text('$first $last'),
)

// Or for any number of variables:
ObserverN(
  listenable: [firstName, lastName, age, city],
  listener: () => Text('${firstName.value} ${lastName.value}'),
)

7️⃣ Type-Safe Reactive Types #

Built-in types for common use cases:

final name = ReactiveString('John');
final age = ReactiveInt(25);
final score = ReactiveDouble(98.5);
final isActive = ReactiveBool(true);
final items = ReactiveList<String>(['A', 'B', 'C']);
final tags = ReactiveSet<String>({'flutter', 'dart'});

// Or use generic for custom types
final user = Reactive<User>(User());

8️⃣ Smart Dependency Management #

// Register with overwrite warning
Dependency.put(MyController());

// Conditional registration
Dependency.putIfAbsent(() => MyController());

// Check if registered
if (Dependency.isRegistered<MyController>()) {
  // Use it
}

// Fenix mode - auto-recreate after deletion
Dependency.put(MyController(), fenix: true);

// Reset all dependencies
Dependency.reset();

📚 Documentation #

Core Concepts #

  • 📖 Getting Started Guide - Step-by-step tutorial
  • 📚 API Reference - Complete API documentation
  • 🚀 Advanced Patterns - Best practices & patterns
  • ⚡ Quick Reference - Cheat sheet
  • 🆕 What's New in v1.0.0 - New features guide

Migration & Upgrading #

  • From 0.3.x to 1.0.0: No changes needed! 100% backward compatible
  • From GetX: Similar API, easier to learn
  • From Provider/Riverpod: Less boilerplate, same power

💡 Examples #

Basic Counter #

final count = ReactiveInt(0);

Observer(
  listenable: count,
  listener: (value) => Text('Count: $value'),
)

Search with Debounce #

class SearchController extends ReactiveController {
  final searchQuery = ReactiveString('');
  final results = ReactiveList<String>([]);

  SearchController() {
    searchQuery.setDebounce(Duration(milliseconds: 500));
    searchQuery.ever((query) => _performSearch(query));
  }

  void updateQuery(String query) {
    searchQuery.updateDebounced(query);
  }

  Future<void> _performSearch(String query) async {
    if (query.isEmpty) {
      results.clear();
      return;
    }
    final data = await api.search(query);
    results.value = data;
  }
}

Form with Undo/Redo #

class FormController extends ReactiveController {
  final name = ReactiveString('', enableHistory: true);
  final email = ReactiveString('', enableHistory: true);

  bool get canUndo => name.canUndo || email.canUndo;
  
  void undoAll() {
    if (name.canUndo) name.undo();
    if (email.canUndo) email.undo();
  }
}

Shopping Cart with Computed Total #

class CartController extends ReactiveController {
  final items = ReactiveList<CartItem>([]);
  late final ComputedReactive<double> total;

  CartController() {
    total = ComputedReactive(
      () => items.fold(0.0, (sum, item) => sum + item.price),
      dependencies: [items],
    );
  }
}

📁 See Full Examples


🆚 Comparison with GetX #

Reactiv is inspired by GetX but with key improvements:

✅ Advantages over GetX #

  1. Explicit Listening - Observer knows exactly what it's listening to (no magic)
  2. Compile-Time Safety - Red lines if you forget to specify what to listen to
  3. Optimized by Design - Encourages writing performant code
  4. Focused Package - ~150 APIs vs GetX's 2400+ APIs
  5. Better Performance - Batched updates, optimized rebuilds
  6. Production Features - Undo/redo, computed values, debounce built-in

Code Comparison #

Reactiv:

Observer(
  listenable: controller.count, // Explicit - you know what updates this
  listener: (count) => Text('$count'),
)

GetX:

Obx(() {
  // Implicit - any reactive var here triggers rebuild
  final count = controller.count.value;
  return Text('$count');
})

🎯 Best Practices #

✅ Do's #

// ✅ Use specific observers
Observer(listenable: count, listener: (val) => Text('$val'))

// ✅ Enable history only when needed
final text = ReactiveString('', enableHistory: true);

// ✅ Use computed for derived state
final total = ComputedReactive(() => items.sum(), [items]);

// ✅ Debounce expensive operations
searchQuery.setDebounce(Duration(milliseconds: 500));

// ✅ Use lazy loading for heavy controllers
Dependency.lazyPut(() => HeavyController());

❌ Don'ts #

// ❌ Don't use Observer at root of entire page
Observer(
  listenable: controller.anything,
  listener: (_) => EntirePageWidget(), // Rebuilds everything!
)

// ❌ Don't enable history on everything
final x = ReactiveInt(0, enableHistory: true); // Unless you need it

// ❌ Don't forget to dispose
// Always call Dependency.delete() or use autoDispose

🔧 Configuration #

Disable Logging in Production #

import 'package:flutter/foundation.dart';
import 'package:reactiv/reactiv.dart';

void main() {
  // Disable logging in release mode
  if (kReleaseMode) {
    Logger.enabled = false;
  }
  
  runApp(MyApp());
}

📊 Performance #

Reactiv is designed for performance:

  • Batched Updates: Multiple mutations = single rebuild
  • Optimized Observers: No unnecessary widget rebuilds
  • Smart Memory Management: Automatic cleanup, zero leaks
  • Lazy Loading: Create controllers only when needed
  • Debounce/Throttle: Built-in performance optimization

🤝 Contributing #

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Contributors #

Thanks to all contributors! ❤️


📄 License #

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.


🌟 Show Your Support #

If you like Reactiv, please:

  • ⭐ Star the repo on GitHub
  • 👍 Like the package on pub.dev
  • 📢 Share with the Flutter community
  • 🐛 Report issues or suggest features

📞 Support & Community #


Made with ❤️ for the Flutter Community

Get StartedView on GitHubpub.dev

6
likes
0
points
42
downloads

Publisher

verified publisherreactivlibrary.dev

Weekly Downloads

Production-ready reactive state management with robust logging, undo/redo, computed values, debounce/throttle, and more. Lightweight, powerful, and easy to use.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on reactiv