A light, powerful and reactive state management for Flutter Apps.

Overview

Reactter


Pub Publisher Reactter Flutter Reactter Pub points MIT License GitHub Workflow Status Codecov

A light, powerful and reactive state management.

Features

  • โšก๏ธ Build for speed.
  • ๐Ÿ“ Reduce boilerplate code significantly.
  • ๐Ÿ“ Improve code readability.
  • ๐Ÿชƒ Unidirectional data flow.
  • โ™ป๏ธ Reuse state using custom hooks.
  • ๐Ÿช„ No configuration necessary.
  • ๐ŸŽฎ Total control to re-render widget tree.
  • ๐Ÿ’™ Flutter or Dart only, you can use in any Dart project.

Contents

Quickstart

Before anything, you need to be aware that Reactter is distributed on two packages, with slightly different usage.

The package of Reactter that you will want to install depends on the project type you are making.

Select one of the following options to know how to install it:

Dart onlyโ€‚ Reactter

Add the package on your project.

  • Using command:

    dart pub add reactter
  • Or put directly into pubspec.yaml file:

      dependencies:
        reactter: #add version here

    and run dart pub get.

Now in your Dart code, you can use:

import 'package:reactter/reactter.dart';

Flutterโ€‚ Flutter Reactter

Add the package on your project.

  • Using command:

    flutter pub add flutter_reactter
  • Or put directly into pubspec.yaml file:

      dependencies:
        flutter_reactter: #add version here

    and run flutter pub get.

Now in your Dart code, you can use:

import 'package:flutter_reactter/flutter_reactter.dart';

Usage

reactter Concept Diagram

Create a ReactterContext

ReactterContext is a abstract class that allows to manages ReactterHook and provides life-cycle events.

You can use it's functionalities, creating a class that extends it:

class AppContext extends ReactterContext {}

RECOMMENDED: Name class with Context suffix, for easy locatily.

Lifecycle of ReactterContext

ReactterContext has the following Lifecycle events:

  • Lifecycle.registered: Event when the instance has registered by ReactterInstanceManager.

  • Lifecycle.unregistered: Event when the instance has unregistered by ReactterInstanceManager.

  • Lifecycle.inicialized: Event when the instance has inicialized by ReactterInstanceManager.

  • Lifecycle.willMount: Event when the instance will be mount in the widget tree (it use with flutter_reactter only).

  • Lifecycle.didMount: Event when the instance did be mount in the widget tree (it use with flutter_reactter only).

  • Lifecycle.willUpdate: Event when any instance's hooks will be update. Event param is a ReactterHook.

  • Lifecycle.didUpdate: Event when any instance's hooks did be update. Event param is a ReactterHook.

  • Lifecycle.willUnmount: Event when the instance will be unmount in the widget tree(it use with flutter_reactter only).

  • Lifecycle.destroyed: Event when the instance did be destroyed by ReactterInstanceManager.

You can put it on listen, using UseEvent, for example:

  UseEvent<AppContext>().on<ReactterHook>(
    Lifecycle.didUpdate,
    (inst, hook) => print("Instance: $inst, hook: $hook"),
  );

Manage instance with ReactterInstanceManage

ReactterInstanceManager is a instance of Reactter that exposes some methods to manages instance. These are some methods:

Reactter.register: Registers a builder function to allows to create the instance using Reactter.get.

Reactter.register(builder: () => AppContext());
Reactter.register(id: "uniqueId", builder: () => AppContext());

Reactter.unregister: Removes the builder function to avoid create the instance.

Reactter.unregister<AppContext>();
Reactter.unregister<AppContext>("uniqueId");

Reactter.get: Gets the previously instance created or creates a new instance from the build registered using reactter.register.

final appContext = Reactter.get<AppContext>();
final appContextWithId = Reactter.get<AppContext>(id: 'uniqueId');

Reactter.create: Registers, creates and gets the instance directly.

final appContext = Reactter.create(build: () => AppContext());
final appContextWithId = Reactter.create(id: 'uniqueId', build: () => AppContext());

Reactter.delete: Deletes the instance but still keep the build function.

Reactter.delete<AppContext>();
Reactter.delete<AppContext>('uniqueId');

NOTE: The registered instances have a global scope. This means that you can access them anywhere in the project just by using Reactter.get or through UseContext.

Using UseContext hook

UseContext is a ReactterHook that allows to get ReactterContext's instance when it's ready.

class AppContext extends ReactterContext {
  late final otherContextHook = UseContext<OtherContext>(context: this);
  // final otherContextHookWithId = UseContext<OtherContext>(id: "uniqueId", context: this);
  late otherContext = otherContext.instance;

  AppContext() {
    UseEffect(() {
      otherContext = otherContextHook.instance;
    }, [otherContextHook]);
  }
}

NOTE: If you're not sure that you got the instance from the beginning, you need to use the UseEffect as shown in the example above.

NOTE: The context that you need to get, must be created by ReactterInstanceManager.

Using UseEvent hook

UseEvent is a ReactterHook that manages events.

You can listen to event using on method:

enum Events { SomeEvent };

void _onSomeEvent(inst, param) {
  print("$inst's Events.SomeEvent emitted with param: $param.");
}

UseEvent<AppContext>().on(Events.SomeEvent, _onSomeEvent);

Use off method to stop listening event:

UseEvent<AppContext>().off(Events.SomeEvent, _onSomeEvent);

If you want to listen event only once, use one method:

UseEvent<AppContext>().one(Events.SomeEvent, _onSomeEvent);

And use emit method to trigger event:

UseEvent<AppContext>().emit(Events.SomeEvent, 'Parameter');

IMPORTANT: Don't forget to remove event using off or using dispose to remove all instance's events. Failure to do so could increase memory usage or have unexpected behaviors, such as events in permanent listening.

RECOMMENDED: If you have the instance, use directly with UseEvent.withInstance(<instance>).

Using UseState hook

UseState is a ReactterHook that manages a state.

You can add it on any part of class, with the context argument(this) to put this hook on listen:

class AppContext extends ReactterContext {
  late final count = UseState(0, this);
}

or add it into listenHooks method which is exposed by ReactterContext:

class AppContext extends ReactterContext {
  final count = UseState(0);

  AppContext() {
    listenHooks([count]);
  }
}

NOTE: If you don't add context argument or use listenHook, the ReactterContext won't be able to react to hook's changes.

UseState has value property that allows to read and write its state:

class AppContext extends ReactterContext {
  late final count = UseState(0, this);

  AppContext() {
    print("Prev state: ${count.value}");
    count.value = 10;
    print("Current state: ${count.value}");
  }
}

NOTE: UseState notifies that its state has changed when the previous state is different from the current state. If its state is a Object, not detect internal changes, only when states is setted another Object.

If you want to force notify, execute update method, which is exposed by UseState.

class Todo {
  String name;

  Todo(this.name);
}

class AppContext extends ReactterContext {
  final todoState = UseState(Todo('Do this'), this);

  AppContext() {
    todoState.update(() {
      todoState.value.name = 'Do this other';
    });
  }
}

Using UseAsyncState hook

UseAsyncState is a ReactterHook with the same functionality as UseState but provides a asyncValue method, which will be obtained when resolve method is executed.

class TranslateArgs {
  final String to;
  final String from;
  final String text;

  TranslateArgs({ this.to, this.from, this.text });
}

class AppContext extends ReactterContext {
  late final translateState = UseAsyncStates<String, TranslateArgs>(
    'Hello world',
    translate,
    this,
  );

  AppContext() {
    _init();
  }

  Future<void> _init() async {
    await translateState.resolve(
      TranslateArgs({
        to: 'ES',
        from: 'EN',
        text: translateState.value,
      }),
    );

    print("'Hello world' translated to Spanish: '${translateState.value}'");
  }

  Future<String> translate([TranslateArgs args]) async {
    return await api.translate(args);
  }
}

NOTE: If you want to send argument to asyncValue method, need to define a type argument which be send through resolve method. Like the example shown above, the argument type send is TranslateArgs class.

It also has when method that returns a new value depending on it's state:

final valueComputed = asyncState.when<String>(
  standby: (value) => "โš“๏ธ Standby: $value",
  loading: (value) => "โณ Loading...",
  done: (value) => "โœ… Resolved: $value",
  error: (error) => "โŒ Error: $error",
);

Using UseReducer hook

UseReducer is a ReactterHook that manages state using reducer method. An alternative to UseState.

RECOMMENDED: UseReducer is usually preferable to UseState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

UseReducer accepts three arguments:

 UseReducer(<reducer>, <initialState>, <context>);
  • The reducer method contains your custom state logic that calculates the new state using current state, and actions.
  • The initialState is a unique value of any type with which you initialize the state.
  • The context represents any instance of the ReactterContext which is notified of any change in state.

UseReducer exposes a dispatch method that allows to invoke the reducer method sending a ReactterAction.

The current state can be access through value property.

Here's the counter example:

class Store {
 final int count;

 Store({this.count = 0});
}

Store _reducer(Store state, ReactterAction<String, int?> action) {
 switch (action.type) {
   case 'INCREMENT':
     return Store(count: state.count + (action.payload ?? 1));
   case 'DECREMENT':
     return Store(count: state.count + (action.payload ?? 1));
   default:
     throw UnimplementedError();
 }
}

class AppContext extends ReactterContext {
 late final state = UseReducer(_reducer, Store(count: 0), this);

 AppContext() {
   print("count: ${state.value.count}"); // count: 0;
   state.dispatch(ReactterAction(type: 'INCREMENT', payload: 2));
   print("count: ${state.value.count}"); // count: 2;
   state.dispatch(ReactterAction(type: 'DECREMENT'));
   print("count: ${state.value.count}"); // count: 1;
 }
}

Also, you can create the actions as a callable class, extending from ReactterActionCallable and use them like this:

class Store {
  final int count;

  Store({this.count = 0});
}

class IncrementAction extends ReactterActionCallable<Store, int> {
  IncrementAction({int quantity = 1}) : super(type: 'INCREEMNT', payload: quantity);

  @override
  Store call(Store state) => Store(count: state.count + payload);
}

class DecrementAction extends ReactterActionCallable<Store, int> {
  DecrementAction({int quantity = 1}) : super(type: 'DECREMENT', payload: quantity);

  @override
  Store call(Store state) => Store(count: state.count - payload);
}

Store _reducer(Store state, ReactterAction action) =>
  action is ReactterActionCallable ? action(state) : UnimplementedError();

class AppContext extends ReactterContext {
  late final state = UseReducer(_reducer , Store(count: 0), this);

  AppContext() {
    print("count: ${state.value.count}"); // count: 0;
    state.dispatch(IncrementAction(quantity: 2));
    print("count: ${state.value.count}"); // count: 2;
    state.dispatch(DecrementAction());
    print("count: ${state.value.count}"); // count: 1;
  }
}

Using UseEffect hook

UseEffect is a ReactterHook that manages side-effect.

You can add it on constructor of class:

class AppContext extends ReactterContext {
  late final count = UseState(0, this);

  AppContext() {
    UseEffect((){
      // Execute by count state changed or 'didMount' event
      print("Count: ${count.value}");

      Future.delayed(
        const Duration(seconds: 1),
        () => count.value += 1,
      );

      return () {
        // Cleanup - Execute Before count state changed or 'willUnmount' event
        print("Cleanup executed");
      };
    }, [count], this);
  }
}

If you want to execute a UseEffect immediately, use UseEffect.dispatchEffect instead of the context argument:

UseEffect(
  () => print("Excute immediately or by hook's changes"),
  [someHook],
  UseEffect.dispatchEffect
);

NOTE: If you don't add context argument to UseEffect, the callback don't execute on lifecycle didMount, and the cleanup don't execute on lifecycle willUnmount(theses lifecycle events are used with flutter_reactter only).

Create a ReactterHook

ReactterHook is a abstract class that allows to create a Custom Hook.

There are several advantages to using Custom Hooks:

  • Reusability: you can use the same hook again and again, without the need to write it twice.
  • Clean Code: extracting part of context logic into a hook will provide a cleaner codebase.
  • Maintainability: easier to maintain. if we need to change the logic of the hook, you only need to change it once.

Here's the counter example:

class UseCount extends ReactterHook {
  int _count = 0;

  int get value => _count;

  UseCount(int initial, [ReactterContext? context])
      : _count = initial,
        super(context);

  void increment() => update(() => _count += 1);
  void decrement() => update(() => _count -= 1);
}

RECOMMENDED: Name class with Use preffix, for easy locatily.

NOTE: ReactterHook provides update method which notify to context that has changed.

and use it like that:

class AppContext extends ReactterContext {
  late final count = UseCount(0, this);

  AppContext() {
    UseEffect(() {
      Future.delayed(
        const Duration(seconds: 1),
        count.increment,
      );

      print("Count: ${count.value}");
    }, [count], this);
  }
}

Global state

The reactter's hooks can be defined as static to access its as global way:

class Global {
  static final flag = UseState(false);
  static final count = UseCount(0);

  // Create a class factory to run it as singleton way.
  // This way, the initial logic can be executed.
  static final Global _inst = Global._init();
  factory Global() => _inst;

  Global._init() {
    UseEffect(() {
      Future.delayed(const Duration(seconds: 1), changeCount);
    }, [count], UseEffect.dispatchEffect);
  }

  static void changeCount() {
    if (count.value <= 0) {
      flag.value = true;
    }

    if (count.value >= 10) {
      flag.value = false;
    }

    flag.value ? count.increment() : count.decrement();
  }
}

// It's need to create the instance it to be able
// to execute Global._init(This executes only once).
final global = Global();

This is a example that how you could use it:

class AppContext extends ReactterContext {
  late final isOdd = UseState(false, this);

  AppContext() {
    UseEffect((){
      isOdd.value = Global.count.value % 2 != 0;
    }, [Global.count], this);
  }
}

NOTE: If you want to execute some logic when initialize the global class, you need to use the class factory and then instance it to run as singleton way.

Usage with flutter_reactter

flutter_reactter Concept Diagram

Wrap with ReactterProvider

ReactterProvider is a wrapper StatelessWidget that provides a ReactterContext's instance to widget tree that can be access through the BuildContext.

ReactterProvider(
  () => AppContext(),
  builder: (context, child) {
    final appContext = context.watch<AppContext>();
    return Text("count: ${appContext.count.value}");
  },
)

If you want to create a different ReactterContext's instance, use id parameter.

ReactterProvider(
  () => AppContext(),
  id: "uniqueId",
  builder: (context, child) {
    final appContext = context.watchId<AppContext>("uniqueId");
    return Text("count: ${appContext.count.value}");
  },
)

IMPORTANT: Dont's use ReactterContext with constructor parameters to prevent conflicts. Instead use onInit method to access its instance and put the data you need.

NOTE: ReactteProvider is a "scoped". So it contains a ReactterScope which the builder callback will be rebuild, when the ReactterContext changes. For this to happen, the ReactterContext should put it on listens for BuildContext's watchers.

Access to ReactterContext

Reactter provides additional methods to BuildContext to access your ReactterContext. These are following:

  • context.watch: Gets the ReactterContext's instance from the closest ancestor of ReactterProvider and watch all ReactterHook or ReactterHook defined in first paramater.
final watchContext = context.watch<WatchContext>();
final watchHooksContext = context.watch<WatchHooksContext>(
  (ctx) => [ctx.stateA, ctx.stateB],
);
  • context.watchId: Gets the ReactterContext's instance with id from the closest ancestor of ReactterProvider and watch all ReactterHook or ReactterHook defined in second paramater.
final watchIdContext = context.watchId<WatchIdContext>('id');
final watchHooksIdContext = context.watchId<WatchHooksIdContext>(
  'id',
  (ctx) => [ctx.stateA, ctx.stateB],
);
  • context.use: Gets the ReactterContext's instance with/without id from the closest ancestor of ReactterProvider.
final readContext = context.use<ReadContext>();
final readIdContext = context.use<ReadIdContext>('id');

NOTE: These methods mentioned above uses ReactterProvider.contextOf

NOTE: context.watch and context.watchId watch all or some of the specified ReactterHook dependencies and when it will change, re-render widgets in the scope of ReactterProviders, ReactterBuilder or ReactterScope.

Control re-render with ReactterScope

ReactterScope is a wrapeer StatelessWidget that to to control re-rendered of widget tree.

ReactterScope<AppContext>(
  builder: (context, child) {
    final appContext = context.watch<AppContext>();
    return Text("Count: ${appContext.count.value}");
  },
)

NOTE: The builder callback will be rebuild, when the ReactterContext changes. For this to happen, the ReactterContext should put it on listens for BuildContext's watchers.

Control re-render with ReactterBuilder

ReactterBuilder is a wrapper StatelessWidget that to to get the ReactterContext's instance from the closest ancestor of ReactterProvider and exposes it through the first parameter of builder callback.

ReactterBuilder<AppContext>(
  listenAllHooks: true,
  builder: (appContext, context, child) {
    return Text("Count: ${appContext.count.value}");
  },
)

NOTE: ReactterBuilder is read-only by default(listenAllHooks: false), this means it only renders once. Instead use listenAllHooks as true or use listenHooks with the ReactterHooks specific and then the builder callback will be rebuild with every ReactterContext's ReactterHook changes.

NOTE: ReactterBuilder is a "scoped". So it contains a ReactterScope which the builder callback will be rebuild, when the ReactterContext changes. For this to happen, the ReactterContext should put it on listens for BuildContext's watchers.

Multiple ReactterProvider with ReactterProviders

ReactterProviders is a wrapper StatelessWidget that allows to use multiple ReactterProvider as nested way.

ReactterProviders(
  [
    ReactterProvider(() => AppContext()),
    ReactterProvider(
      () => ConfigContext(),
      id: 'App',
      onInit: (appConfigContext) {
        appConfigContext.config.value = 'new state';
      },
    ),
    ReactterProvider(
      () => ConfigContext(),
        id: 'User'
    ),
  ],
  builder: (context, child) {
    final appContext = context.watch<AppContext>();
    final appConfigContext = context.watchId<ConfigContext>('App');
    final userConfigContext = context.watchId<ConfigContext>('User');
    ...
  },
)

Create a ReactterComponent

ReactterComponent is a abstract StatelessWidget class that provides the functionality of ReactterProvider with a ReactterContext and exposes it through render method.

class CounterComponent extends ReactterComponent<AppContext> {
  const CounterComponent({Key? key}) : super(key: key);

  @override
  get builder => () => AppContext();

  @override
  get id => 'uniqueId';

  @override
  listenHooks(appContext) => [appContext.stateA];

  @override
  Widget render(appContext, context) {
    return Text("StateA: ${appContext.stateA.value}");
  }
}

Resources

Roadmap

We want to keeping adding features for Reactter, those are some we have in mind order by priority:

  • Widget to control re-render using only hooks
  • Async context.
  • Do benchmarks and improve performance.

Contribute

If you want to contribute don't hesitate to create an issue or pull-request in Reactter repository.

You can:

  • Provide new features.
  • Report bugs.
  • Report situations difficult to implement.
  • Report an unclear error.
  • Report unclear documentation.
  • Add a new custom hook.
  • Add a new widget.
  • Add examples.
  • Translate documentation.
  • Write articles or make videos teaching how to use Reactter.

Any idea is welcome!

Authors

You might also like...

The typesafe, reactive, and lightweight SQLite abstraction for your Flutter applications

The typesafe, reactive, and lightweight SQLite abstraction for your Flutter applications

See the project's website for the full documentation. Floor provides a neat SQLite abstraction for your Flutter applications inspired by the Room pers

Dec 28, 2022

The Reactive Extensions for Dart

RxDart About RxDart extends the capabilities of Dart Streams and StreamControllers. Dart comes with a very decent Streams API out-of-the-box; rather t

Dec 20, 2022

A Widget that passes a Reactive Model to all of it's children

scoped_model A set of utilities that allow you to easily pass a data Model from a parent Widget down to its descendants. In addition, it also rebuilds

Nov 30, 2022

An example of "reactive/streaming repository" as a solution for BLoC to BLoC communication

An example of

Reactive Repositories An example of listening to a Stream from repository layer (instead of explicitly using get/fetch) as a solution for BLoC to BLoC

Jan 3, 2023

Multiplayer tictactoe game made in Flutter with nodejs and socket.io and using riverpod for state management

Multiplayer tictactoe game made in Flutter with nodejs and socket.io and using riverpod for state management

TicTacToe Game A Multiplayer TicTacToe Game- Works on Android, iOS and Web. Features Create/Join Room Play Realtime Display Points Round & Game Winner

Oct 18, 2022

An atomic state management library for dart (and Flutter). Simple, fast and flexible.

nucleus An atomic dependency and state management toolkit. Design goals Simplicity - simple API with no surprises Performance - allow for millions of

Jan 2, 2023

Note provider - Note App using Provider state management, Sqflite and Localization for two language Arabic and English.

note_provider Sqflite with provider statemanagement Getting Started This project is a starting point for a Flutter application. A few resources to get

Jan 1, 2022
Releases(v4.1.0)
  • v4.1.0(Dec 31, 2022)

    Enhancements

    • perf(core): Improve performance for changing states.
    • perf(engine): Improve management for context dependencies.

    Fixes

    • fix(core): Remove the callbacks of one events when the instance will be disposed.

    Internal

    • refactor(example): Improve examples and fix some bugs.
    • doc: Fix documentation.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v4.0.0...v4.1.0

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Nov 16, 2022)

    Enhancements

    • feat(core): Add Obj.
    • feat(core): Add Signal.
    • feat(core): Add ReactterSignalProxy mixin.
    • feat(core): Add ReactterNotifyManager mixin.
    • feat(core): Add ReactterState mixin.
    • refactor(core,hooks): Manage event separate from UseEvent hook.
    • perf(core): Improve to manage instances.
    • perf(core): Improve to manage state.
    • perf(widgets,core): Improve performance on ReactterProvider. Now there is no need to use ReactterComponent or ReactterBuilder. The instance can be accessed directly from the context(BuildContext) and just the part belonging to the context is re-built.
    • feat(widgets): Add ReactterWatcher. You can use the Signal variable in ReactterWatcher and react when it changed for ReactterWatcher's widgets rebuild.

    Breaking

    • refactor(core): Remove typedef innecesary.
    • refactor(hooks): Fix dispose of UseContext and UseEffect.
    • build(widgets): Mark ReactterScope as deprecated. Use any Widget that exposes the BuildContext like Build, StatelessWidget or StatefulWidget instead.
    • build(widgets): Mark listenHooks and listenAllHooks as deprecated. Use listenStates and listenAll instead.
    • refactor(widgets): Remove onInit from ReactteProvider and ReactterComponent.
    • refactor(widget): Add ReactterContext argument in builder of ReactterProvider.

    Fixes

    • fix(core): Don't allow increasing listeners count, if event don't exist.
    • fix(widgets): Clear previous signals saved.
    • fix(core): Remove one callback using off method and was changed how to storage event.

    Internal

    • test: Refactor test and add event manager test.
    • refactor(test): Fix test and add new tests.
    • build(engine): Rename some files.
    • refactor(test): Fix test and add ReactterWatcher test.
    • refactor(examples): Improve examples code and add calculator example.
    • doc: Fix documentation and add new documentation.
    • test(core,hooks): Fix dispose on some tests.
    • refactor(examples): Do counter more simple.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v3.2.0...v4.0.0

    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Sep 9, 2022)

    Enhancements

    Breaking

    • refactor(core): Replace ReactterInstanceManager extension to class.

    Fixes

    • refactor(hooks): Move events storage variable.

    Internal

    • refactor(examples): Improve examples code.
    • docs: Update roadmap.
    • docs: Fix some typos and improve documentation.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v3.1.2...v3.2.0

    Source code(tar.gz)
    Source code(zip)
  • v3.1.2(Jul 21, 2022)

    Fixes

    • fix(core): Add ref on Reactter.create.

    Internal

    • docs: Fix some documentation.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v3.1.1...v3.1.2

    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(Jul 15, 2022)

    Fixes

    • fix(widgets): Fix child and builder of ReactterProvider is not required when use ReactterProviders.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v3.1.0...v3.1.1

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Jul 15, 2022)

    Breaking

    • refactor(core): Remove selector aspect from ReactterProvider.of.

    Fixes

    • fix(core): Fix ReactterInstanceManager's get method create instance when instance didn't create yet.
    • refactor(engine, widgets): Add validations about child and builder properties.

    Enhancements

    • refactor(core): Change Reactter.delete named argument to positional argument.

    Internal

    • docs: Fix README documentation.
    • refactor(tests): Add test coverage of 100%.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v3.0.0...v3.1.0

    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(Jul 14, 2022)

    Breaking

    Enhancements

    • feat(widgets): Improve finding ReactterContext in the widget tree via the BuildContext. Now the operation of finding ReactterContext is O(1) and ReactterContext using id is O(2).
    • refactor(hooks): Add more Lifecycle events(Lifecycle.registered,Lifecycle.unregistered,Lifecycle.registered and Lifecycle.destroyed)
    • feat(hooks): Add UseContext hook.
    • feat(hooks): Add UseEvent hook.
    • feat(widgets): Add ReactterScope widget.
    • refactor(core): Add Reactter.create and Reactter.find.

    Full Changelog: https://github.com/2devs-team/reactter/compare/2.3.3...v3.0.0

    Source code(tar.gz)
    Source code(zip)
  • v2.3.3(Jun 14, 2022)

    Enhancements

    • refactor(core,widget): Remove life cycle class and move it to reactter_context.

    Internal

    • reactor(example): Move buttons and fix typo on tree example.
    • docs(example): Change description of some examples.
    • docs: Remove assets and change README.
    • docs: Add README to example.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v2.3.2...2.3.3

    Source code(tar.gz)
    Source code(zip)
  • v2.3.2(Jun 11, 2022)

    Fixes

    • fix: format reactter.dart and remove an unnecessary dart file

    Full Changelog: https://github.com/2devs-team/reactter/compare/v2.3.1...v2.3.2

    Source code(tar.gz)
    Source code(zip)
  • v2.3.1(Jun 11, 2022)

    Internal

    • fix(example): Fix typo on counter example button.
    • fix(example): Add implement tags on animation example.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v2.3.0...v2.3.1

    Source code(tar.gz)
    Source code(zip)
  • v2.3.0(Jun 11, 2022)

    Breaking

    • refactor: Rename context.of to context.watch.
    • refactor: Rename context.ofId to context.watchId.
    • refactor: Rename context.ofStatic to context.read.
    • refactor: Rename context.ofIdStatic to context.readId.
    • refactor: Move subscribe and publish pattern to ReactterSubscribersManager class. Can use subscribe and publish pattern with enum type specified.
    • refactor(widgets): Use ReactterInheritedProvider as scope on ReactterBuilder.
    • refactor(widgets): Add ReactterBuilder as scope when didn't has builder on ReactterComponent.
    • refactor(core): HookManager subscribe to willUpdate and didUpdate event.
    • refactor(core): WillUpdate and DidUpdate event trigger when its ReactterHook update.
    • refactor(engine): Manage dependencies of ReactterPubSub and lifecycle of ReactterContext.
    • refactor(widget): Performance as the instance of context is listened to mark need build.
    • refactor(hooks, widgets) - Rename UseProvide to ReactterProvider.

    Fixes

    • fix(hooks,widgets): Delete instances of UseContext when dispatch updated event on ReactterProvider, to prevent has instances duplicated.
    • refactor(widget): Fix ReactterBuilder.

    Enhancements

    • feat(widgets): Send id for find ReactterContext on ReactterComponent.
    • feat(widget): Add type on listenerHooks of ReactterBuilder.
    • feat(hooks): Add argument to resolve method of UseAsyncState.
    • feat(hooks): Add lifecycle willUpdate and didUpdate.
    • feat(widget): Add onInit to UseContext.
    • feat(hooks): UseEffect has lifecycle control of the context.
    • feat(hook) UseContext works with unique ids to create unique instances.
    • feat(widget): Add ReactterComponent.
    • refactor(core): Remove context property as public on ReactterHook.
    • feat(engine): Remove dependencies when ReactterProvider unmount.
    • refactor(core): Remove unnecessary event listeners from ReactterContext.
    • refactor(core,hooks): Remove unnecessary code.
    • refactor(engine): Remove props unnecessary on ReactterInheritedProvider.
    • refactor(hooks): Clear code and do code simple on UseAsyncState.
    • refactor(core): Improve performance how instances manager on ReactterFactory.
    • refactor(core): Improve UseEffect. Now the return of callback execute when a hook was change or willUnmount event was invoke.
    • refactor(core): Improve lifecycle events. Now it uses as subscription.

    Internal

    • docs: Fix some documentation.
    • feat(example): Add more example with animation.
    • feat(example): Add new examples.
    • docs: Add badgets, reorder topic, fix examples and improve redaction on README.
    • docs: Add more documentation.
    • tests: Add tests for hooks and Widgets.

    Full Changelog: https://github.com/2devs-team/reactter/compare/v1.0.1...v2.3.0

    Source code(tar.gz)
    Source code(zip)
  • v2.3.0-dev.3(Jun 11, 2022)

    [2.3.0-dev.3] - Dev Release 2022-06-11

    Changed

    • refactor: Rename context.of to context.watch.
    • refactor: Rename context.ofId to context.watchId.
    • refactor: Rename context.ofStatic to context.read.
    • refactor: Rename context.ofIdStatic to context.readId.

    Added

    • feat(example): Add more example with animation
    Source code(tar.gz)
    Source code(zip)
  • v2.2.0-dev.1(Jun 10, 2022)

    [2.2.0-dev.1] - Dev Release 2022-06-10

    Changed

    • refactory(core,engine,hooks,widget): Move subscribe and publish pattern to ReactterSubscribersManager class. Can use subscribe and publish pattern with enum type specified.
    • refactor(core,hooks): Remove unnecessary code.
    • fix(hooks,widgets): Delete instances of UseContext when dispatch updated event on ReactterProvider, to prevent has instances duplicated.
    • refactor(widgets): Use ReactterInheritedProvider as scope on ReactterBuilder.
    • refactor(engine): Remove props unnecessary on ReactterInheritedProvider.
    • refactor(core): Improve performance how instances manager on ReactterFactory.
    • refactor(widgets): Add ReactterBuilder as scope when didn't has builder on ReactterComponent.
    • refactor(hooks): Clear code and do code simple on UseAsyncState.
    • refactor(core): Remove context property as public on ReactterHook.

    Added

    • feat(example): add new examples.
    • docs: Add badgets, reorder topic, fix examples and improve redaction on README.
    Source code(tar.gz)
    Source code(zip)
  • v2.1.0-dev.2(May 25, 2022)

  • v2.1.0-dev.1(May 24, 2022)

    [2.1.0-dev.1] - Dev Release 2022-04-24

    Changed

    • fix(widgets): Send id for find ReactterContext on ReactterComponent.
    • feat(engine):: Remove dependencies when ReactterProvider unmount.
    • refactor(core): Remove unneccesaries event listeners from ReactterContext.
    • refactor(core): HookManager subscribe to willUpdate and didUpdate event.
    • refactor(core): WillUpdate and DidUpdate event trigger when its ReactterHook update.
    • refactor(engine): Manage dependencies of ReactterPubSub and lifecycle of ReactterContext.
    • refactor(widget): Performance as the instance of context is listen to mark need build.
    • refacor(widget): Fix ReactterBuilder.
    • refactor(core): Improve UseEffect now the return of callback execute when a hook was change or willUnmount event was invoke.
    • refactor(core): Improve lifecycle events now it use as subscription.

    Added

    • docs: Add more documentation.
    • tests: Add tests for hooks and Widgets.
    • feat(widget): Add type on listenerHooks of ReactterBuilder.
    • feat(hooks): Add argument to resolve method of UseAsyncState.
    • feat(hooks): Add lifecycle willUpdate and didUpdate.
    • feat(widget): Add onInit to UseContext.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(May 24, 2022)

    [1.0.1] - 2022-03-31

    Changed

    • Fix some documentation.
    • Removed Utils folder from library.

    Added

    • Improve performance with primitive loops in functions.
    Source code(tar.gz)
    Source code(zip)
A powerful state machine for MobX management, that can be used in almost any application state.

A powerful state machine for MobX management, which can be used in almost any application state. It has 3 states - loading, success, error - and is pe

Daniel Magri 8 Oct 31, 2022
โšกFQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps.

โšก FQuery is a powerful async state management solution for flutter. It caches, updates and fully manages asynchronous data in your flutter apps. It ca

Piyush 21 Dec 22, 2022
An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.

Frideos An all-in-one package for state management, streams and BLoC pattern, animations and timed widgets, effects. Contents 1. State management Gett

Francesco Mineo 188 Dec 23, 2022
Practice building basic animations in apps along with managing app state by BLoC State Management, Flutter Slider.

Practice building basic animations in apps along with managing app state by BLoC State Management including: Cubit & Animation Widget, Flutter Slider.

TAD 1 Jun 8, 2022
Nimbostratus is a reactive data-fetching and client-side cache management library built on top of Cloud Firestore.

Nimbostratus ?? Nimbostratus is a reactive data-fetching and client-side cache management library built on top of Cloud Firestore. The Cloud Firestore

Dan Reynolds 13 Dec 15, 2022
a simple yet powerful state management technique for Flutter

States_rebuilder `states_rebuilder` is Flutter state management combined with a dependency injection solution and an integrated router to get the best

MELLATI Fatah 480 Jan 2, 2023
Simple yet powerful form state management

formini Working with forms shouldn't be so hard in Flutter. Please note that the schemani/formini packages are under development. There are still some

Vantage Oy 1 Dec 12, 2019
State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Flutter Community 70 Sep 28, 2022
Shopify Tag and Product Management App using Flutter and Riverpod State Management

Myshopify App A Simple Flutter Application project to get List of Tags, Products and Product Details from shopify https://shopicruit.myshopify.com/adm

Idowu Tomiwa 5 Nov 12, 2022
An extension to the bloc state management library which lets you create State Machine using a declarative API

An extension to the bloc state management library which lets you create State Machine using a declarative API

null 25 Nov 28, 2022