reactter 1.0.0-dev reactter: ^1.0.0-dev copied to clipboard
A light state management with React syntax.
Reactter by 2devs.io #
[1.0.0-dev] - #
Changed #
-
No need package dependencies: We decided to remove all dependencies and create a new state management from scratch.
-
Controller now is Context:
ReactterController
has been replaced byReactterContext
, which are the classes that going to manage our states.class AppContext extends ReactterContext {}
Added #
-
Two ways to manage state: You can control the listeners from context like this:
class AppContext extends ReactterContext { /* You can create the state here and add it to dependencies in constructor with listenHooks() */ final username = UseState<String>(""); AppContext(){ listenHooks([username]); } /* But we recommend to give the context to the state this way: With this, you no longer need to put it in listenHooks() which is cleaner */ late final firstName = UseState<String>("Leo", context: this); late final lastName = UseState<String>("León", context: this); }
-
Added UseProvider widget:
UseProvider
provide allReactterContext
to his children.UseProvider( contexts: [ UseContext( () => AppContext(), init: true, ), ], builder: (context, _) { // Get all the states listeners of context. final appContext = context.of<AppContext>(); // Get the listener of an specific state to rebuild. final appContext = context.of<AppContext>((ctx) => [ctx.userName]); // Read all the states, but no rebuild when change. final appContextStatic = context.ofStatic<AppContext>(); return Text(appContext.username.value); } );
-
Remove UseEffect widget: This widget has been replaced by a class called
UseEffect
. It has exactly the same functionality as theReact Hook
, when a dependency changes, executes the callback parameter.UseEffect((){ userName.value = firstName + lastName; }, [firstName, lastName]);
Note: UseEffect has to be called inside context constructor.
-
Added custom Hooks: You can create your own hooks with mixin inherit from
ReactterHook
.mixin UseCart on ReactterHook { late final cart = UseState<Cart?>(null, context: this); addProductToCart(Product product) { final oldProducts = cart.value.products; cart.value = cart.value? .copyWith(products: [...oldProducts, product]); } }
-
Added UseAsyncState class: If you need an async state, you can use this:
class AppContext extends ReactterContext { ... late final userName = UseAsyncState<String>("Init state", fillUsername, context: this); Future<String> fillUsername() async { final userFromApi = await getUserName(); return userFromApi; } ... }
-
Added UseAsyncState.when function: Added this function to controll the async flow from
UseAsyncState
:... ), userContext.userName.when( // Base state standby: (value) => Text("Standby: " + value), // When is executing the async code loading: () => const CircularProgressIndicator(), // When the async code has finished done: (value) => Text(value), // When it throw an error error: (error) => const Text( "Unhandled exception", style: TextStyle(color: Colors.red), ), ), ...
-
Added lifecycle methods to ReactterContext:
@override awake() { // Executes when the instance starts building. } @override willMount() { // Before the dependency widget will mount in the tree. } @override didMount() { // After the dependency widget did mount in the tree. } @override willUnmount() { // When the widget removes from the tree. }