nuke 0.0.7

  • Readme
  • Changelog
  • Example
  • Installing
  • 46

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.

[0.0.7] #

  • Support tagging of observables

[0.0.6] #

  • $rx.$ref as factory instead of static method

[0.0.5] #

  • Guard against accidental null RX matchers

[0.0.4] #

  • $RX is now RX
  • Dropped named paramed from RX
  • $ref is now $rx.$ref
  • Allow observables to be disposed via nuke.dispose()

[0.0.3] #

  • Update syntax
  • Support computed values

[0.0.2] #

  • Update syntax

[0.0.1] #

  • Initial release.

example/lib/main.dart

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

void main()=>runApp(MyApp());

final $n = Nuke();

class MyApp extends StatelessWidget
{
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}


class MyHomePage extends StatelessWidget
{

  final simple = $rx(0, ref:'simple/0');

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

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

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  nuke: ^0.0.7

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:nuke/nuke.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
81
Overall:
Weighted score of the above. [more]
46
Learn more about scoring.

We analyzed this package on Jul 11, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • nuke that is a package requiring null.

Health suggestions

Format lib/nuke.impl.dart.

Run flutter format to format lib/nuke.impl.dart.

Format lib/nuke.wgt.dart.

Run flutter format to format lib/nuke.wgt.dart.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

The package description is too short. (-9 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.0 <3.0.0
equatable ^1.2.0 1.2.2
flutter 0.0.0
path_to_regexp ^0.3.0 0.3.0
uuid ^2.0.4 2.2.0
Transitive dependencies
charcode 1.1.3
collection 1.14.12 1.14.13
convert 2.1.1
crypto 2.1.5
meta 1.1.8 1.2.2
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test