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