jaspr_getx_distil 1.0.0 copy "jaspr_getx_distil: ^1.0.0" to clipboard
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).

example/lib/main.dart

// jaspr_getx_distil 최소 SPA example.
//
// * 앱 전체 수명 서비스는 루트 `BindingComponent(eager: true)`에 둔다 (immortal `GetxService`).
// * 화면 수명 Controller는 각 라우트의 `BindingComponent` 스코프에 둔다.
// * ShellRoute = feature 스코프: shell Binding은 자식 라우트 이동에도 유지된다.
//
// 실행: `cd example && jaspr serve`
import 'package:jaspr/dom.dart';
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: 'jaspr_getx_distil example', body: const App()));
}

// ─── 앱 전체 수명 = immortal GetxService ────────────────────────────────────

/// 유저 세션 같은 앱 수명 서비스. 루트 eager 스코프에서 immortal로 등록된다.
class SessionService extends GetxService {
  final Rx<String> displayName = Rx<String>('guest');
  int closeCount = 0;

  @override
  void onClose() {
    closeCount++;
    super.onClose();
  }
}

// ─── 화면 수명 = scoped Controller ──────────────────────────────────────────

/// `/` 화면 컨트롤러. BindingComponent가 unmount되면 onClose 후 registry 제거.
class HomeController extends GetxController {
  final Rx<int> count = Rx<int>(0);

  /// Rx 값을 바꾸고 `update()`로 GetBuilder 리스너를 깨운다.
  void increment() {
    count.value++;
    update();
  }
}

/// `/other` 화면 컨트롤러.
class AboutController extends GetxController {
  final Rx<String> message = Rx<String>('about');
}

// ─── 화면 (GetView) ─────────────────────────────────────────────────────────

class HomePage extends GetView<HomeController> {
  const HomePage({super.key});

  @override
  Component build(BuildContext context) {
    final controller = this.controller;
    return div([
      h1([.text('jaspr_getx_distil example')]),
      // Obx는 동기 build가 읽은 Rx만 추적한다. leaf만 감싼다.
      Obx(() => p([.text('count: ${controller.count.value}')])),
      button(onClick: () => controller.increment(), [.text('+1')]),
      // GetxController.update()를 구독하는 명령형 빌더. increment()가
      // update()를 호출하면 이 리스너가 rebuild된다.
      GetBuilder<HomeController>(
        builder: (c) => span([.text('update() → ${c.count.value}')]),
      ),
      // 전역 서비스는 라우트 이동 후에도 find 가능.
      nav([
        Link(to: '/about', child: span([.text('Go to about')])),
      ]),
    ]);
  }
}

class AboutPage extends GetView<AboutController> {
  const AboutPage({super.key});

  @override
  Component build(BuildContext context) {
    final controller = this.controller;
    return div([
      h1([.text('About')]),
      Obx(() => p([.text('message: ${controller.message.value}')])),
      nav([
        Link(to: '/', child: span([.text('Go home')])),
      ]),
    ]);
  }
}

// ─── 앱 / 라우트 ────────────────────────────────────────────────────────────

/// ShellRoute = feature 스코프. 자식 `/` `/about` 이동에도 유지되는 기능
/// 서비스. eager BindingComponent 위에서 immortal이 된다.
class ShellBinding extends GetxService {
  final Rx<int> pings = Rx<int>(0);
}

class App extends StatelessComponent {
  const App({super.key});

  @override
  Component build(BuildContext context) {
    return BindingComponent(
      key: Key('root-services'),
      eager: true,
      bindings: [
        // GetxService는 eager BindingComponent 위에서 immortal이 된다. 프로세스
        // 전역 static이므로 SSR에선 요청 시작 시 Get.reset()으로 재설정한다.
        Bind<SessionService>(() => SessionService()),
      ],
      child: Router(
        routes: [
          // ShellRoute.builder는 (context, state, child)를 받아 shell을 감싼다.
          // 이 BindingComponent는 자식 라우트가 바뀌어도 unmount되지 않는다.
          ShellRoute(
            builder: (_, _, child) => BindingComponent(
              key: Key('shell'),
              eager: true,
              bindings: [Bind<ShellBinding>(() => ShellBinding())],
              child: child,
            ),
            routes: [
              Route(
                path: '/',
                builder: (_, _) => BindingComponent(
                  key: Key('home'),
                  bindings: [Bind<HomeController>(() => HomeController())],
                  child: const HomePage(),
                ),
              ),
              Route(
                path: '/about',
                builder: (_, _) => BindingComponent(
                  key: Key('about'),
                  bindings: [Bind<AboutController>(() => AboutController())],
                  child: const AboutPage(),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
69
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A distilled reactive state-management and hybrid scoped-DI engine for Jaspr (GetX DX, Component tree).

Homepage
Repository (GitHub)
View/report issues

Topics

#jaspr #state-management #getx #reactive

License

MIT (license)

Dependencies

jaspr

More

Packages that depend on jaspr_getx_distil