Flutter Redux Framework

A portrait painting style image of a pirate holding an iPhone.

by The Captain

on
May 15, 2023

A Comprehensive Guide to Flutter Redux Framework

Flutter Redux is a predictable state container for Dart applications, providing an easy-to-use way to manage application state throughout the application. This framework follows a unidirectional state flow approach that helps developers easily manage and maintain a clean application architecture. To get started with Flutter Redux, first, we need to install the required packages using the following command:
dependencies:
  flutter:
    sdk: flutter
  flutter_redux: ^0.8.2
  redux: ^3.0.0}
Next, we need to define our application state, actions, and reducer function. The state is a plain Dart object that stores all the data that needs to be persisted in the application.
class AppState {
  final bool isLoading;
  final List items;

  AppState({this.isLoading = false, this.items = const []});

  AppState copyWith({bool isLoading, List items}) {
    return AppState(
      isLoading: isLoading ?? this.isLoading,
      items: items ?? this.items,
    );
  }
}

enum Actions { AddItem, RemoveItem, ToggleLoading }

AppState reducer(AppState state, dynamic action) {
  if (action == Actions.ToggleLoading) {
    return state.copyWith(isLoading: !state.isLoading);
  }

  if (action is Actions.AddItem) {
    return state.copyWith(items: List.from(state.items)..add(action.item));
  }

  if (action is Actions.RemoveItem) {
    return state.copyWith(
        items: List.from(state.items)..remove(action.item));
  }

  return state;
}
Once we have defined our application state, actions, and reducer function, we can create a store that holds the application state and dispatch the actions using the store. We can access or update the state of our application from anywhere in the application using the store.
void main() {
  final store =
      Store(reducer, initialState: AppState());

  runApp(MyApp(store: store));
}

class MyApp extends StatelessWidget {
  final Store store;

  MyApp({Key key, this.store}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: MaterialApp(
        title: 'Flutter Redux Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(),
      ),
    );
  }
}
In the above example, we have created a store using the reducer and initial state of the application and passed it in the StoreProvider widget. We can use the StoreConnector widget throughout the application to retrieve the current state of the application, dispatch actions, or pass the state to child widgets.
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Redux Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            StoreConnector(
              converter: (store) => store.state.isLoading,
              builder: (context, isLoading) => Visibility(
                visible: isLoading,
                child: CircularProgressIndicator(),
              ),
            ),
            StoreConnector>(
              converter: (store) => store.state.items,
              builder: (context, items) => Column(
                children: items
                    .map((item) => ListTile(
                          title: Text(item),
                          trailing: IconButton(
                            icon: Icon(Icons.delete),
                            onPressed: () =>
                                store.dispatch(Actions.RemoveItem(item)),
                          ),
                        ))
                    .toList(),
              ),
            ),
            Container(
              padding: EdgeInsets.all(16.0),
              child: StoreConnector(
                converter: (store) =>
                    (item) => store.dispatch(Actions.AddItem(item)),
                builder: (context, addItem) => TextFormField(
                  onFieldSubmitted: (value) {
                    addItem(value);
                    Navigator.of(context).pop();
                  },
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => store.dispatch(Actions.ToggleLoading),
        child: Icon(Icons.add),
      ),
    );
  }
}
In the above example, we have used the StoreConnector widget to retrieve the isLoading and items from the application state and render them accordingly. We have also used the dispatch method of the store to dispatch the actions when required. Flutter Redux provides an easy and effective way to manage application state in a predictable and organized manner. By following a unidirectional state flow pattern, it provides a structure that is easy to maintain and scale.