A high-performance Flutter state management tool built with alien_signals
, Oref is one of the fastest Flutter signals and state management solutionsthe other being Solidart.
Much of the pain in state management in Dart & Flutter comes from reacting to changes in given values, because the values themselves are not directly observable. We have to use StatefulWidget
or other state management tools for state, which use inefficient proactive notifications or a large number of watchers to notify widgets to rebuild, and the boilerplate code is very redundant.
Fortunately, there were later pioneers like signals
built by Rody Davis and Solidart
by Alexandru Mariuti who first brought signals to Flutter. However, they also faced a problem: requiring developers to abandon StatelessWidget
and adopt their specific base classes or watchers.
The release of alien_signals
completely changed Flutter's inefficient state management situation, but Flutter state libraries still require a lot of boilerplate code! Oref completely changes this situation. In Flutter, when a Widget accesses a signal value, if that signal's value changes, the Widget is automatically rebuilt.
class Counter extends StatelessWidget {
@override
Widget build(BuildContext context) {
final count = useSignal(context, 0);
void increment() => count(count + 1);
return Column(children: [
Text('Count: ${count()}'),
TextButton(
onPressed: increment,
child: Text('click me'),
)
]);
}
}
Signals are magically injected into the BuildContext to provide optimal performance and ergonomic design. In the example above, we access count()
to get the current value of the signal and complete the responsive binding with the current Counter
. When the count value is updated, it automatically notifies the Counter to rebuild.
You can install by editing your pubspec.yaml
file:
dependencies:
oref: latest
Or install by running this command:
flutter pub add oref
Let's use signals in a real-world scenario. We'll build a todo list application where you can add and remove items from the todo list. We'll start by modeling the state. We first need a signal containing a list of todos, which we can represent with an "array":
import "package:oref/oref.dart";
final todos = createGlobalSignal([
"Buy groceries",
"Walk the dog"
]);
To allow users to enter text for new todos, we also need a signal that indicates we'll soon connect to a form element. Now, we can already use this signal to create a function that adds todos to our list.
({
TextEditingController controller,
void Function() insert
}) useTodo(BuildContext context) {
final controller = useComputed(context, (_) => TextEditingController());
void insert() {
todos([...todos(), controller.text]);
controller.clear();
}
return (controller: untrack(controller), insert: insert);
}
Tip
A signal only updates when you assign a new value to it. If the value you assign to a signal equals its current value, it won't update.
final count = useSignal(context, 0);
count(0); // Nothing happens - the value is already 0
count(1); // Updates - the value is different
The last feature we want to add is the ability to remove todos from the list. For this, we'll add a function to remove a given todo from the todos array:
void removeTodo(String todo) {
todos(todos.where((e) => e != todo));
}
Now that we've modeled the application's state, it's time to connect a beautiful UI that users can interact with.
class TodosWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final todo = useTodo(context);
return Column(
children: [
TextFormField(controller: todo.controller),
TextButton(onPressed: todo.insert, child: const Text("Add")),
for (final item in todos())
ListTile(
title: Text(item),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () => removeTodo(item),
),
);
],
);
}
}
And there we have it - a fully functional todo application!
TODO
Oref doesn't have a dedicated documentation website, but you can view details through the API Reference in pub.dev or source code comments.
Oref is an MIT licensed open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider sponsoring Seven(@medz) development.
Thank you to all the people who already contributed to Oref!