watchable_redux 1.0.0 copy "watchable_redux: ^1.0.0" to clipboard
watchable_redux: ^1.0.0 copied to clipboard

discontinued

Predictable state management for Flutter. Redux architecture with O(1) selector caching, memoized selectors, async middleware, and time-travel debugging. Built on Watchable.

example/main.dart

import 'package:flutter/material.dart';
import 'package:watchable_redux/watchable_redux.dart';

// State
class AppState {
  final int counter;
  final List<String> todos;
  final bool isLoading;

  const AppState({
    this.counter = 0,
    this.todos = const [],
    this.isLoading = false,
  });

  AppState copyWith({
    int? counter,
    List<String>? todos,
    bool? isLoading,
  }) {
    return AppState(
      counter: counter ?? this.counter,
      todos: todos ?? this.todos,
      isLoading: isLoading ?? this.isLoading,
    );
  }
}

// Actions
sealed class AppAction extends ReduxAction {
  const AppAction();
}

class Increment extends AppAction {
  const Increment();
}

class Decrement extends AppAction {
  const Decrement();
}

class AddTodo extends AppAction {
  final String text;
  const AddTodo(this.text);
}

class RemoveTodo extends AppAction {
  final int index;
  const RemoveTodo(this.index);
}

class SetLoading extends AppAction {
  final bool loading;
  const SetLoading(this.loading);
}

// Reducer
AppState appReducer(AppState state, ReduxAction action) {
  return switch (action) {
    Increment() => state.copyWith(counter: state.counter + 1),
    Decrement() => state.copyWith(counter: state.counter - 1),
    AddTodo(:final text) => state.copyWith(todos: [...state.todos, text]),
    RemoveTodo(:final index) => state.copyWith(
        todos: [...state.todos]..removeAt(index),
      ),
    SetLoading(:final loading) => state.copyWith(isLoading: loading),
    _ => state,
  };
}

// Selectors
final selectCounter = (AppState s) => s.counter;
final selectTodos = (AppState s) => s.todos;
final selectTodoCount = createSelector<AppState, List<String>, int>(
  selectTodos,
  (todos) => todos.length,
);

// Async action example
ThunkAction<AppState> fetchTodosAsync() {
  return ThunkAction((dispatch, getState) async {
    dispatch(const SetLoading(true));
    await Future.delayed(const Duration(seconds: 1));
    dispatch(const AddTodo('Fetched todo 1'));
    dispatch(const AddTodo('Fetched todo 2'));
    dispatch(const SetLoading(false));
  });
}

// Store
final store = Store<AppState>(
  initialState: const AppState(),
  reducer: appReducer,
  middlewares: [
    loggerMiddleware(),
    thunkMiddleware(),
  ],
  enableDevTools: true,
);

void main() {
  Redux.init(store);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return StoreProvider<AppState>(
      store: store,
      child: MaterialApp(
        title: 'Watchable Redux Demo',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: const HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Watchable Redux'),
        actions: [
          IconButton(
            icon: const Icon(Icons.undo),
            onPressed: () => store.devTools?.undo(),
          ),
          IconButton(
            icon: const Icon(Icons.redo),
            onPressed: () => store.devTools?.redo(),
          ),
        ],
      ),
      body: const Column(
        children: [
          CounterSection(),
          Divider(),
          TodoSection(),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => store.dispatch(fetchTodosAsync()),
        child: const Icon(Icons.download),
      ),
    );
  }
}

class CounterSection extends StatelessWidget {
  const CounterSection({super.key});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          IconButton(
            icon: const Icon(Icons.remove),
            onPressed: () => Redux.dispatch(const Decrement()),
          ),
          store.build(
            selectCounter,
            (count) => Text(
              '$count',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ),
          IconButton(
            icon: const Icon(Icons.add),
            onPressed: () => Redux.dispatch(const Increment()),
          ),
        ],
      ),
    );
  }
}

class TodoSection extends StatelessWidget {
  const TodoSection({super.key});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Row(
              children: [
                Text(
                  'Todos: ',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                store.build(
                  selectTodoCount,
                  (count) => Text(
                    '$count',
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                ),
              ],
            ),
          ),
          Expanded(
            child: store.build(
              selectTodos,
              (todos) => ListView.builder(
                itemCount: todos.length,
                itemBuilder: (context, index) => ListTile(
                  title: Text(todos[index]),
                  trailing: IconButton(
                    icon: const Icon(Icons.delete),
                    onPressed: () => Redux.dispatch(RemoveTodo(index)),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
0
points
11
downloads

Documentation

Documentation

Publisher

verified publisherdipendrasharma.com

Weekly Downloads

Predictable state management for Flutter. Redux architecture with O(1) selector caching, memoized selectors, async middleware, and time-travel debugging. Built on Watchable.

Repository (GitHub)
View/report issues

Topics

#state-management #redux #flutter #reactive #watchable

License

unknown (license)

Dependencies

flutter, watchable

More

Packages that depend on watchable_redux