ZenState LogoZenState
Introducing ZenState v0.1

Where Flutter State Meets Simplicity

A thoughtfully designed state management solution for Flutter developers who value clarity, performance, and maintainable code architecture.

Reactive
Predictable
Composable
Performant

Be an early adopter! Join our growing community and help shape the future of Flutter state management.

Flutter
Dart
Firebase
Provider
Material

Simple, Elegant API

ZenState's clean API makes state management straightforward while giving you powerful tools when you need them.

counter_example.dart
1// Simple state with Atoms
2final counterAtom = Atom<int>(0);
3
4// Update state with a clean API
5void increment() => counterAtom.value++;
6
7// Use in widgets with minimal boilerplate
8class CounterWidget extends StatelessWidget {
9  
10  Widget build(BuildContext context) {
11    // Watch the atom and rebuild when it changes
12    final count = counterAtom.watch(context);
13    
14    return Column(
15      children: [
16        Text('Count: $count', style: Theme.of(context).textTheme.headline4),
17        ElevatedButton(
18          onPressed: increment,
19          child: Text('Increment'),
20        ),
21      ],
22    );
23  }
24}

Powerful Features, Elegant Design

ZenState combines simplicity with advanced capabilities to give you complete control over your app's state.

Reactive Atoms

Granular state units that automatically track dependencies and optimize UI updates.

Command Pattern

Encapsulate state changes in explicit, testable command objects for better organization.

Computed State

Derived values that automatically update when their dependencies change.

Async Support

First-class support for async operations with loading and error states.

Persistence

Easily save and restore state with built-in persistence adapters.

Developer Tools

Time-travel debugging and state inspection for a better development experience.

How ZenState Works

A clean architecture that makes state management intuitive and maintainable.

profile_screen.dart
1// 1. Define your feature module
2class TodoFeature extends ZenFeature {
3  
4  String get name => 'todos';
5  
6  // State containers
7  late final todosAtom = registerAtom('items', <Todo>[]);
8  
9  // Derived state (computed automatically)
10  late final completedCountDerived = registerDerived(
11    'completedCount',
12    () => todosAtom.value.where((todo) => todo.completed).length
13  );
14  
15  // Commands for operations
16  late final toggleTodoCommand = registerFunctionCommand<String, void>(
17    'toggleTodo',
18    (id) {
19      todosAtom.update((todos) => todos.map((todo) => 
20        todo.id == id ? todo.copyWith(completed: !todo.completed) : todo
21      ).toList());
22    },
23  );
24}
25
26// 2. Use the feature in your widgets
27Widget buildTodoList(BuildContext context) {
28  // Access the feature
29  final todoFeature = context.feature<TodoFeature>();
30  
31  // Watch state changes
32  final todos = todoFeature.todosAtom.watch(context);
33  final completedCount = todoFeature.completedCountDerived.watch(context);
34  
35  return Column(
36    children: [
37      Text('Completed: $completedCount / ${todos.length}'),
38      Expanded(
39        child: ListView.builder(
40          itemCount: todos.length,
41          itemBuilder: (context, index) => CheckboxListTile(
42            title: Text(todos[index].title),
43            value: todos[index].completed,
44            onChanged: (_) => todoFeature.toggleTodoCommand.execute(todos[index].id),
45          ),
46        ),
47      ),
48    ],
49  );
50}

Atomic State

Break your state into small, focused atoms that are easy to reason about and test.

Command Pattern

Encapsulate state changes in explicit commands for better organization and testability.

Reactive UI

UI components automatically update when their state dependencies change, with minimal rebuilds.

Composable Architecture

Compose complex state from simple building blocks, creating a scalable architecture.

Advanced Use Cases

ZenState scales elegantly from simple counter apps to complex enterprise applications.

todo_app_example.dart
1// Smart optimization with context awareness
2class SearchFeature extends ZenFeature {
3  
4  String get name => 'search';
5  
6  // Query with debouncing and context awareness
7  late final queryAtom = registerSmartAtom(
8    'query',
9    '',
10    // Debounce rapid typing
11    optimizer: DebouncingOptimizer<String>(
12      duration: Duration(milliseconds: 300),
13    ),
14    // Adapt based on device conditions
15    contextFactors: [BatteryFactor(), NetworkFactor()],
16  );
17  
18  // Search results with loading state
19  late final resultsAtom = registerAtom('results', <SearchResult>[]);
20  late final searchFuture = registerFuture<List<SearchResult>>('search');
21  
22  // Perform search when query changes
23  SearchFeature() {
24    // Listen to query changes
25    queryAtom.addListener(_onQueryChanged);
26  }
27  
28  void _onQueryChanged() {
29    if (queryAtom.value.isEmpty) {
30      resultsAtom.value = [];
31      return;
32    }
33    
34    // Use the correct load method from ZenFuture
35    searchFuture.load(() async {
36      final results = await searchService.search(queryAtom.value);
37      resultsAtom.value = results;
38      return results;
39    });
40  }
41  
42  
43  void dispose() {
44    queryAtom.removeListener(_onQueryChanged);
45    super.dispose();
46  }
47}
48
49// Usage in a widget
50class SearchScreen extends StatelessWidget {
51  
52  Widget build(BuildContext context) {
53    final searchFeature = context.feature<SearchFeature>();
54    final query = searchFeature.queryAtom.watch(context);
55    final results = searchFeature.resultsAtom.watch(context);
56    final isLoading = searchFeature.searchFuture.isLoading;
57    
58    return Column(
59      children: [
60        TextField(
61          onChanged: (value) => searchFeature.queryAtom.value = value,
62          decoration: InputDecoration(
63            hintText: 'Search...',
64            suffixIcon: isLoading ? CircularProgressIndicator() : null,
65          ),
66        ),
67        Expanded(
68          child: searchFeature.searchFuture.when(
69            initial: () => Center(child: Text('Enter a search term')),
70            loading: () => Center(child: CircularProgressIndicator()),
71            success: (data) => ListView.builder(
72              itemCount: results.length,
73              itemBuilder: (context, index) => ListTile(
74                title: Text(results[index].title),
75              ),
76            ),
77            error: (error, stackTrace) => Center(
78              child: Text('Error: ${error.toString()}'),
79            ),
80          ),
81        ),
82      ],
83    );
84  }
85}

Reactive by Design

ZenState automatically tracks dependencies between state atoms and derived values, ensuring your UI updates efficiently when data changes.

Explicit State Changes

Commands encapsulate state mutations, making your code more maintainable and easier to test. Each state change is explicit and traceable.

Ready to simplify your state management?

Start building more maintainable Flutter applications today with ZenState's elegant and powerful approach.

ZenState is a new library looking for early adopters and contributors

Join our community