nuke

Super slim, lightweight, practical state management < 250 lines of code.

Not for the faint hearted, PRs super appreciated.

To the point:

Counter app

import 'package:nuke/nuke.dart';

class MyHomePage extends StatelessWidget
{
  final counter = $rx(0, ref:'ref/0');

  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context)
  {
    return Scaffold
    (
      body: Center
      (
        child: RX(const ['ref/:any'], (context) =>
          Text(counter.value.toString()))
          //alternatively $rx.$ref('ref/0').value
      ),
      floatingActionButton: FloatingActionButton
      (
        onPressed: ()=>counter.value++,
        //alternatively $rx.$ref('ref/0').value++
        child: const Icon(Icons.add),
      ),
    );
  }
}

Where's my state?

Hence the name.

Let's break it down:

final counter = $rx(0, ref:'ref/0');
  • 0 is our initial value
  • ref reference the observalbe value at 'ref/0'
//intentionally not named (aka matchers:[], builder:(context)) to keep it short
child: RX(const ['ref/:any'], (context) =>
  Text($rx.$ref('ref/0').value.toString()))
  • the observer widget name
  • a list of names / regex scopes the widget should listen to
  • $rx.$ref('ref/0').value obtain the value by reference

counter.value also works, the above used for illustation purposed.

More on matchers, consider this:

final counter1 = $rx(0, ref:'ref/0');
final counter2 = $rx(0, ref:'ref/1');

@override
Widget build(BuildContext context)=>
  RX(const ['ref/0', 'ref/1'], (context)=>Container());

The above widget will be rebuilt whenever either counter1 or counter2 change their values.

Alternatively:

@override
Widget build(BuildContext context)=>
  RX(const ['ref/:idx'], (context)=>Container());

References are awesome because they allow observers to be defined and acessed anywhere within the app.

A practical example would be a "aettings" screen where value X is utilized within the underlying widget, saving hassle of passing values between the two separate widgets and updating each's local state.

Banana republic multi counter app

class MyHomePage2 extends StatelessWidget
{
  final counters = {
    'x': 'y',
    'a': {
      'b': {
        'c': $rx(0, ref:'counter/0'),
        'wtf': [$rx(0, ref:'counter/1'), $rx(0, ref:'counter/2')],
      },
    }
  };

  int sum()=>
    Iterable.generate(3).map((i)=>$rx.$ref('counter/$i').value as int)
      .reduce((a,b )=>a+b);

  void increment()=>
    Iterable.generate(3).forEach((i)=>$rx.$ref('counter/$i').value++);

  MyHomePage2({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context)
  {
    return Scaffold
    (
      body: Center
      (
        child: Wrap(spacing:20, children:
        [
          //Listens to all observables on counter/:any
          RX(const ['counter/:any'],(context) =>Text('${sum()}')),

          //Listens only to counter/1
          RX(const ['counter/1'], (context) => Text('${$rx.$ref('counter/1').value}')),

          //Listens only to counter/2
          RX(['counter/2'], (context) => Text('${$rx.$ref('counter/2').value}')),
        ],),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed:increment, child: const Icon(Icons.add), ),
    );
  }
}

Computed values

final counter1 = $rx(0, ref:'ref/0');
final counter2 = $rx(0, ref:'ref/1');

final sum = $cmp(['ref/0', 'ref/1'],
  ()=>$rx.$ref('ref/0').value+$rx.$ref('ref/1').value, ref:'ref/sum')

Tagging

final counter1 = $rx(0, ref:'ref/0', tags:['dirty']);
final counter2 = $rx(0, ref:'ref/1', tags:['dirty']);

nuke.diposeTagged(['dirty', 'whatever'], matchAny:true)

Clean up

$RX automatically cleans up observable subscriptions, however, to dispose observables that are no longer in use, call nuke.dispose([ref]).

Pub sub

import 'package:nuke/nuke.dart';

final $n = Nuke();

//subscribe
final subKey = $n.subscribe(['topic'], (topic, data)=>print(data));

//publish
$n.publish('topic', {'foo':1});

//unsubscribe
$n.unsubscribe(subKey);

What's up with the $

Just to avoid accedential conflicts and keep name conventions short.

Libraries

nuke
nuke.impl
nuke.wgt