oref 2.6.0 copy "oref: ^2.6.0" to clipboard
oref: ^2.6.0 copied to clipboard

A high-performance Flutter state management tool, Oref is one of the fastest Flutter signals and state management solutions.

example/lib/main.dart

import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:oref/oref.dart';

void main() {
  runApp(const ExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Oref Examples',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
      ),
      home: const ExampleHome(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Oref Examples')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: const [
          _Section(
            title: 'Counter + computed + writableComputed',
            child: CounterSection(),
          ),
          SizedBox(height: 16),
          _Section(
            title: 'Effect + batch',
            child: EffectBatchSection(),
          ),
          SizedBox(height: 16),
          _Section(
            title: 'untrack()',
            child: UntrackSection(),
          ),
          SizedBox(height: 16),
          _Section(
            title: 'useAsyncData',
            child: AsyncDataSection(),
          ),
        ],
      ),
    );
  }
}

class _Section extends StatelessWidget {
  const _Section({required this.title, required this.child});

  final String title;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 0,
      color: Theme.of(context).colorScheme.surfaceContainerHighest,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(title, style: Theme.of(context).textTheme.titleMedium),
            const SizedBox(height: 12),
            child,
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final count = signal<double>(context, 2);
    final doubled = computed<double>(context, (_) => count() * 2);
    final squared = writableComputed<double>(
      context,
      get: (_) => count() * count(),
      set: (value) {
        final safe = value < 0 ? 0.0 : value;
        count.set(math.sqrt(safe));
      },
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('count: ${count().toStringAsFixed(1)}'),
        Text('doubled (computed): ${doubled().toStringAsFixed(1)}'),
        Text('squared (writable): ${squared().toStringAsFixed(1)}'),
        const SizedBox(height: 8),
        Wrap(
          spacing: 8,
          children: [
            ElevatedButton(
              onPressed: () => count.set(count() + 1),
              child: const Text('Increment'),
            ),
            OutlinedButton(
              onPressed: () => squared.set(81),
              child: const Text('Set squared = 81'),
            ),
          ],
        ),
      ],
    );
  }
}

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'),
            ),
          ],
        ),
      ],
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final source = signal<int>(context, 1);
    final noise = signal<int>(context, 100);
    final tracked = computed<int>(context, (_) => source() + noise());
    final untracked =
        computed<int>(context, (_) => source() + untrack(() => noise()));

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SignalBuilder(
          builder: (context) =>
              Text('source: ${source()}  noise: ${noise()}'),
        ),
        SignalBuilder(builder: (context) => Text('tracked: ${tracked()}')),
        SignalBuilder(builder: (context) => Text('untracked: ${untracked()}')),
        const SizedBox(height: 8),
        Wrap(
          spacing: 8,
          children: [
            ElevatedButton(
              onPressed: () => source.set(source() + 1),
              child: const Text('Bump source'),
            ),
            OutlinedButton(
              onPressed: () => noise.set(noise() + 10),
              child: const Text('Bump noise'),
            ),
          ],
        ),
        const SizedBox(height: 4),
        Text(
          'Note: untracked ignores noise changes.',
          style: Theme.of(context).textTheme.bodySmall,
        ),
      ],
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final requestId = signal<int>(context, 1);
    final result = useAsyncData<String>(
      context,
      () async {
        final id = requestId();
        await Future<void>.delayed(const Duration(milliseconds: 500));
        return 'Result #$id';
      },
      defaults: () => 'Idle',
    );

    final status = result.when(
      context: context,
      idle: (data) => 'Idle: ${data ?? '-'}',
      pending: (data) => 'Loading... ${data ?? ''}',
      success: (data) => 'Success: ${data ?? '-'}',
      error: (error) => 'Error: ${error?.error ?? 'unknown'}',
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('request id: ${requestId()}'),
        Text(status),
        const SizedBox(height: 8),
        Wrap(
          spacing: 8,
          children: [
            ElevatedButton(
              onPressed: () => requestId.set(requestId() + 1),
              child: const Text('Next request'),
            ),
            OutlinedButton(
              onPressed: () async {
                await result.refresh();
              },
              child: const Text('Refresh'),
            ),
          ],
        ),
      ],
    );
  }
}
14
likes
160
points
352
downloads

Publisher

verified publishermedz.dev

Weekly Downloads

A high-performance Flutter state management tool, Oref is one of the fastest Flutter signals and state management solutions.

Repository (GitHub)
View/report issues

Topics

#signals #reactive #state-management #alien-signals

Documentation

API reference

Funding

Consider supporting this project:

github.com
opencollective.com

License

MIT (license)

Dependencies

alien_signals, flutter

More

Packages that depend on oref