Widgets
When creating a UI, it makes sense to boil down individual views to their functional requirements:
- displaying certain data/state
- modifying certain data/state
- wrapping around/displaying other views
As such, UI is often described as a function of state; ReArch takes this one step further by classifying UI as a function of state and any side effect(s).
Sound familiar? It's because capsules are also functions of state and side effect(s)! Just like capsules, you define widgets as functions consuming state and side effect(s).
Full Example
First, let's define some capsules for use in our widgets. Capsules can be defined in the same file as widgets, or in completely separate file(s).
String _salutationCapsule(CapsuleHandle _) => 'Hello';
(String, void Function(String)) firstNameCapsule(CapsuleHandle use) => use.state('Alice');
String greetingCapsule(CapsuleHandle use) {
return '${use(_salutationCapsule)} ${use(firstNameCapsule).$1}!';
}
Next, let's use these capsules in a custom widget.
// Check out Unnested!
// ReArch and Unnested are like peanut butter and jelly, as seen here.
@rearchWidget
Widget myAppBody(WidgetHandle use) {
return Unnest()
.scaffold(appBar: AppBar(title: Text(use(greetingCapsule))))
.center()
.textField(onChanged: use(firstNameCapsule).$2);
}
// ...
MyAppPage(child: const MyAppBody());
Parameters
Any parameters you add to @rearchWidget
functions
are automatically passed onto the generated widget's constructor, similar to @factoryCapsule
.
// Here's a modified version of the above example.
@rearchWidget
Widget greetingWidget(
WidgetHandle use, {
required String greeting,
required Widget child,
}) {
return Column(children: [
Text('$greeting, ${use(firstNameCapsule).$1}!'),
child,
]);
}
// ...
const GreetingWidget(
greeting: 'Hey',
child: Text('Some child widget'),
);
You can even use
@rearchWidget
to create simple stateless widgets too, without the boilerplate; Just don't include theWidgetHandle
parameter!
Here's an example creating a stateless widget with some parameters.
@rearchWidget
Widget myTextCard(BuildContext context, {required String title}) {
return Card(
child: Text(
title,
style: Theme.of(context).textTheme.headlineLarge,
),
);
}
Notice how we depended on the BuildContext
above.
You can also depend on the widget's key
too!
Finally, here's an example creating a simple reusable widget without any parameters.
@rearchWidget
Widget myIcon() {
return Icon(Icons.clock, color: Colors.purple);
}
The RearchBuilder
The RearchBuilder
enables you to delegate building a widget
to a callback that has access to a WidgetHandle
and a BuildContext
.
This can be useful when you want to simply get a new WidgetHandle
inline with some other widgets
when it might not make sense to make an entirely new widget (just like Flutter's Builder
itself).
MyWidget(
child: RearchBuilder(
builder: (context, use) {
return Placeholder();
},
),
);