jaspr_getx_distil 1.0.0
jaspr_getx_distil: ^1.0.0 copied to clipboard
A distilled reactive state-management and hybrid scoped-DI engine for Jaspr (GetX DX, Component tree).
jaspr_getx_distil #
A distilled reactive state-management and hybrid scoped-DI engine for Jaspr (GetX DX, Component tree).
jaspr_getx_distil brings the getx_distil architecture to Jaspr: the same .obs / Obx / Get.find / Worker / Controller developer experience, with hybrid dependency injection (global registry + component-tree scoped BindingComponent) and feature ownership expressed as lifetime.
π Full design rationale (why, hybrid DI, feature scope): see the Flutter getx_distil README. This package keeps the same contracts and swaps the Flutter
Widgettree for a JasprComponenttree. We deliberately do not duplicate the Flutter guide here β read the original, then come back for the Jaspr-specific wiring.
Install #
dependencies:
jaspr: ^0.23.4
jaspr_getx_distil: ^1.0.0
jaspr_router is a dev / example-only dependency β the package itself is runtime-dependent on jaspr only.
Minimal SPA #
Wire jaspr_router with the same ownership pattern as the Flutter original:
import 'package:jaspr/server.dart';
import 'package:jaspr_router/jaspr_router.dart';
import 'package:jaspr_getx_distil/jaspr_getx_distil.dart';
void main() {
Jaspr.initializeApp();
runApp(
Document(title: 'My App', body: const App()),
);
}
class SessionService extends GetxService {
final Rx<String> displayName = Rx<String>('guest');
}
class HomeController extends GetxController {
final Rx<int> count = Rx<int>(0);
void increment() => count.value++;
}
class HomePage extends GetView<HomeController> {
const HomePage({super.key});
@override
Component build(BuildContext context) {
return Obx(() => p([.text('count: ${controller.count.value}')]));
}
}
class App extends StatelessComponent {
const App({super.key});
@override
Component build(BuildContext context) {
return BindingComponent(
key: Key('root-services'),
eager: true,
bindings: [Bind<SessionService>(() => SessionService())],
child: Router(
routes: [
// Feature scope: survives child route changes.
ShellRoute(
builder: (_, _, child) => BindingComponent(
key: Key('shell'),
bindings: [Bind<MyFeatureService>(() => MyFeatureService())],
child: child,
),
routes: [
Route(
path: '/',
builder: (_, _) => BindingComponent(
key: Key('home'),
bindings: [Bind<HomeController>(() => HomeController())],
child: const HomePage(),
),
),
],
),
],
),
);
}
}
Key differences from the Flutter package #
| getx_distil (Flutter) | jaspr_getx_distil |
|---|---|
BindingWidget / InheritedWidget |
BindingComponent / InheritedComponent |
Obx / GetBuilder / GetView β Widget |
β Component |
RxS.on β Widget |
RxS.on β Component |
Get.find({BuildContext? context, String? tag}) |
same, but a Jaspr BuildContext |
GetMaterialApp.bindings |
root BindingComponent(eager: true) |
Flutter Locale (dart:ui) |
package-local Locale(languageCode, countryCode) |
SchedulerBinding / WidgetsBinding |
microtask / Jaspr frame; no SSR wait |
Not ported (Flutter-only): GetMaterialApp, Get.theme / ThemeData / ThemeMode, ValueListenable-based parts, and dart:ui Locale.
SSR guidance #
Get's global registry and immortal GetxService instances are process-global statics, so they survive across server requests. On the server, call Get.reset() at the start of each request to isolate state (the scoped BindingComponent instances are disposed automatically when the request tree unmounts). An @client island does not inherit the server scope β reopen a BindingComponent inside it or rely only on process-global services.
Each test should call Get.reset().
Running the example #
dart pub get
dart test
cd example
dart pub get
jaspr serve
License #
MIT. See LICENSE.
References #
- getx_distil on pub.flutter-io.cn β the Flutter original
- jaspr β the server-rendered Dart framework