joker_state 4.1.0 copy "joker_state: ^4.1.0" to clipboard
joker_state: ^4.1.0 copied to clipboard

Joker is a lightweight, reactive state management solution for Flutter that brings the fun of the circus to your codebase with simple, flexible, and type-safe state handling.

Chinese

🃏 JokerState #

⚠️ Breaking Changes in v4.0.0:

  • CircusRing is now a standalone package. While still usable in JokerState, it no longer provides Joker-specific integration. Please use circus_ring.
  • RingCueMaster now leverages rx_dart for a more robust Event Bus system.
  • JokerStage and JokerFrame constructors are now private. Please use the perform and focusOn APIs instead.
  • Both Joker and Presenter are now based on RxInterface, providing more flexible and efficient state management.
  • RxInterface is built on BehaviorSubject and internally uses Timer for improved autoDispose handling.
  • JokerPortal and JokerCast are deprecated. For context-free state management, use CircusRing API with Presenter.
  • JokerReveal is deprecated. Use Dart's native language features for conditional rendering.
  • JokerTrap is deprecated. Use Presenter's onDone or StatefulWidget's dispose for controller management.

JokerState is a lightweight, reactive Flutter state management toolkit based on rx_dart, with integrated dependency injection via circus_ring.
With just the Joker, Presenter, and CircusRing APIs, you can flexibly manage state and dramatically reduce boilerplate.

pub package License: MIT

Features #

  • 🧠 Reactive State Management: Automatic widget rebuilds and side-effect execution.
  • 💉 Dependency Injection: Simple DI with the CircusRing API.
  • 🪄 Selective Rebuilds: Fine-grained control over what triggers UI updates.
  • 🔄 Batch Updates: Combine multiple state changes into a single notification.
  • 🏗️ Record Support: Combine multiple states using Dart Records.
  • 🧩 Modular Design: Import only what you need, or use the full package.
  • 📢 Event Bus: Type-safe event system via RingCueMaster.
  • ⏱️ Timing Controls: Debounce, throttle, and more for smooth UX.

Quick Start #

Add JokerState to your pubspec.yaml:

dependencies:
  joker_state: ^latest_version

Then import the package:

import 'package:joker_state/joker_state.dart';

Core Concepts #

🎭 Joker: Local Reactive State Container #

Joker<T> is based on RxInterface and provides a local reactive state container. Its lifecycle is mainly managed by listeners and the keepAlive parameter, while providing a whisper API for manual control and a batch API for batch updates.

// Create a Joker (auto-notifies by default)
final counter = Joker<int>(0);

// Update state and notify all listeners
counter.trick(1);

// Update using a function
counter.trickWith((current) => current + 1);

// Or simply
counter.state = 1;

✨ Presenter #

Presenter<T> is an advanced version of Joker. Based on the additional onInit, onReady, and onDone lifecycle hooks, it provides developers with more sophisticated operations and can easily implement BLoC, MVC, and MVVM patterns.

class MyCounterPresenter extends Presenter<int> {
  MyCounterPresenter() : super(0);

  @override
  void onInit() { /* Initialization */ }

  @override
  void onReady() { /* Safe to interact with WidgetsBinding */ }

  @override
  void onDone() { /* Clean up resources */ }

  void increment() => trickWith((s) => s + 1);
}

// Usage:
final myPresenter = MyCounterPresenter();
myPresenter.increment();
// dispose() automatically calls onDone()
myPresenter.dispose(); 

🎪 CircusRing: Dependency Injection #

CircusRing is a lightweight dependency container, now a standalone package (circus_ring), but still usable within JokerState.


🎭 Simple Reactive UI Integration #

JokerState provides various widgets for seamless state and UI integration:

The Simplest Usage

// Using Joker
final userJoker = Joker<User>(...);
userJoker.perform(
  builder: (context, user) => Text('Name: ${user.name}'),
)

// Using Presenter
final myPresenter = MyPresenter(...);
myPresenter.perform(
  builder: (context, state) => Text('State: $state'),
)

For more details, see State Management.

📢 RingCueMaster: Event Bus System #

Type-safe event bus for communication between components:

// Define event type
class UserLoggedIn extends Cue {
  final User user;
  UserLoggedIn(this.user);
}

// Access the global event bus
final cueMaster = Circus.ringMaster();

// Listen for events
final subscription = Circus.onCue<UserLoggedIn>((event) {
  print('User ${event.user.name} logged in at ${event.timestamp}');
});

// Send event
Circus.sendCue(UserLoggedIn(currentUser));

For more details, see Event Bus.

⏱️ CueGate: Timing Controls #

Manage actions with debounce and throttle:

// Create a debounce gate
final debouncer = CueGate.debounce(delay: Duration(milliseconds: 300));

// Use in event handlers
TextField(
  onChanged: (value) {
    debouncer.trigger(() => performSearch(value));
  },
),
// Create a throttle gate
final throttler = CueGate.throttle(interval: Duration(seconds: 1));

// Limit UI updates
scrollController.addListener(() {
  throttler.trigger(() => updatePositionIndicator());
});

// In StatefulWidget, use the mixin for automatic cleanup
class SearchView extends StatefulWidget {
// ...
}

class _SearchViewState extends State<SearchView> with CueGateMixin {
  void _handleSearchInput(String query) {
    debounceTrigger(
      () => _performSearch(query),
      Duration(milliseconds: 300),
    );
  }

  void _handleScroll() {
    throttleTrigger(
      () => _updateScrollPosition(),
      Duration(milliseconds: 100),
    );
  }

// Cleanup handled automatically by mixin
}

For more details, see Timing Controls.

Advanced Features #

🔄 Side-Effects #

Listen for state changes and execute side-effects:

final counter = Joker<int>(0);

counter.effect(
  child: Container(),
  effect: (context, state) {
    print('State changed: $state');
  },
  runOnInit: true,
  effectWhen: (prev, val) => (prev!.value ~/ 5) != (val.value ~/ 5),
);

Additional Info #

JokerState is designed to be lightweight, flexible, and powerful—offering reactive state management and dependency injection in one cohesive package.

When should you use JokerState? #

  • You want something simpler than BLoC or other complex state solutions
  • You need reactive UI updates with minimal boilerplate
  • You want the flexibility to control things manually when needed
  • You need integrated dependency management
  • You prefer clear, direct state operations (not abstract concepts)
  • You need a type-safe event bus for decoupled communication
  • You want utility widgets that work well with your state management

License #

MIT

1
likes
160
points
408
downloads

Publisher

unverified uploader

Weekly Downloads

Joker is a lightweight, reactive state management solution for Flutter that brings the fun of the circus to your codebase with simple, flexible, and type-safe state handling.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

circus_ring, collection, flutter, rxdart

More

Packages that depend on joker_state