Skip to content

Effect 与批处理

基础 Effect

dart
final count = signal(context, 0);
final stop = effect(context, () {
  debugPrint('count = ${count()}');
});

// 手动停止
stop();

清理回调

onEffectCleanup 用于重新执行前清理,onEffectDispose 用于最终清理。

dart
effect(context, () {
  onEffectCleanup(() => debugPrint('cleanup before re-run'));
  onEffectDispose(() => debugPrint('dispose'));
});

EffectScope

dart
final scope = effectScope(context, () {
  effect(context, () => debugPrint('A'));
  effect(context, () => debugPrint('B'));
});

scope(); // 释放范围内所有 effect

批处理更新

dart
batch(() {
  a.set(a() + 1);
  b.set(b() + 1);
});

Flutter 示例(来自 example 应用)

dart
class EffectBatchSection extends StatelessWidget {
  const EffectBatchSection({super.key});

  @override
  Widget build(BuildContext context) {
    final a = signal<int>(context, 1);
    final b = signal<int>(context, 2);
    final sum = computed<int>(context, (_) => a() + b());
    final effectRuns = signal<int>(context, 0);

    effect(context, () {
      sum();
      final current = untrack(() => effectRuns());
      effectRuns.set(current + 1);
    });

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('a: ${a()}  b: ${b()}  sum (computed): ${sum()}'),
        Text('effect runs: ${effectRuns()}'),
        const SizedBox(height: 8),
        Wrap(
          spacing: 8,
          children: [
            ElevatedButton(
              onPressed: () => a.set(a() + 1),
              child: const Text('Increment A'),
            ),
            ElevatedButton(
              onPressed: () => b.set(b() + 1),
              child: const Text('Increment B'),
            ),
            OutlinedButton(
              onPressed: () {
                batch(() {
                  a.set(a() + 1);
                  b.set(b() + 1);
                });
              },
              child: const Text('Batch +1 both'),
            ),
          ],
        ),
      ],
    );
  }
}