jolt_flutter 0.0.3+1
jolt_flutter: ^0.0.3+1 copied to clipboard
A Flutter extension of jolt that provides reactive UI support, enabling automatic synchronization between state and interface.
Jolt Flutter #
A Flutter integration package for Jolt reactive state management, providing reactive UI support and seamless integration between reactive state and Flutter widgets.
Quick Example #
import 'package:flutter/material.dart';
import 'package:jolt_flutter/jolt_flutter.dart';
final counter = Signal(0);
class CounterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Jolt Counter')),
body: Center(
child: JoltBuilder(
builder: (context) => Text(
'Count: ${counter.value}',
style: Theme.of(context).textTheme.headlineMedium,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => counter.value++,
child: Icon(Icons.add),
),
),
);
}
}
Core Concepts #
Signals #
Reactive containers that hold values and notify listeners when changed:
final name = Signal('Flutter');
final count = Signal(0);
// Read values
print(name.value); // 'Flutter'
// Update values
name.value = 'Dart';
count.value++;
Computed Values #
Derived values that automatically update when dependencies change:
final firstName = Signal('John');
final lastName = Signal('Doe');
final fullName = Computed(() => '${firstName.value} ${lastName.value}');
print(fullName.value); // 'John Doe'
firstName.value = 'Jane';
print(fullName.value); // 'Jane Doe' (automatically updated)
Reactive Widgets #
JoltBuilder
Automatically rebuilds when accessed signals change:
JoltBuilder(
builder: (context) => Text('Hello ${name.value}'),
)
JoltSelector
Rebuilds only when a specific selector changes:
final user = Signal(User(name: 'John', age: 30));
JoltSelector(
selector: () => user.value.name,
builder: (context) => Text('Hello ${user.value.name}'),
)
Collection Signals #
Reactive collections that track mutations:
final todos = ['Buy milk', 'Walk dog'].toListSignal();
final settings = {'theme': 'dark'}.toMapSignal();
final tags = {'flutter', 'dart'}.toSetSignal();
// All mutations are tracked
todos.add('Finish project');
settings['theme'] = 'light';
tags.remove('dart');
Async Signals #
Handle asynchronous operations with state tracking:
final userData = AsyncSignal.fromFuture(fetchUser());
JoltBuilder(
builder: (context) => userData.value.when(
loading: () => CircularProgressIndicator(),
data: (user) => UserProfile(user),
error: (error) => Text('Error: $error'),
),
)
Extension Methods #
Convert existing objects to reactive signals:
// Convert any object
final message = 'Hello World'.toSignal();
// Convert collections
final numbers = [1, 2, 3].toListSignal();
// Convert async operations
final apiData = fetchFromApi().toAsyncSignal();
// Convert ValueNotifier (bidirectional sync)
final textController = TextEditingController();
final textSignal = textController.toSignal();
Advanced Usage #
Resource Management with JoltResource #
class TimerStore implements Jolt {
final counter = Signal(0);
Timer? _timer;
@override
void onMount(BuildContext context) {
_timer = Timer.periodic(Duration(seconds: 1), (_) {
counter.value++;
});
}
@override
void onUnmount(BuildContext context) {
_timer?.cancel();
}
}
JoltResource<TimerStore>(
create: (context) => TimerStore(),
builder: (context, store) => Text('Timer: ${store.counter.value}'),
)
Writable Computed Values #
final celsius = Signal(0.0);
final fahrenheit = WritableComputed(
() => celsius.value * 9 / 5 + 32,
(f) => celsius.value = (f - 32) * 5 / 9,
);
fahrenheit.value = 100; // Updates celsius to ~37.78
License #
This project is licensed under the MIT License - see the LICENSE file for details.