This is the 21st day of my participation in the August More Text Challenge

preface

React developers all know the importance of Redux in developing medium and large Web applications. Since Flutter is a high imitator of React and setState has moved here, it is natural that Redux should also move here — good things need to be shared.

Story synopsis

Redux is a one-way data flow state management architecture that simplifies application development, testing, and maintenance. Redux plugin for Flutter

  • redux: All that is needed in FlutterReduxComponents, for exampleStore.ReducerMiddleware.
  • flutter_redux: a special package for Flutter that is packaged on top of Redux to make Flutter easier to use, for exampleStoreProvider(Provided for componentsStoreOn the basis ofWidget),StoreBuilder(fromStoreProviderIn the receivingStoreComponents) andStoreConnector(Used to replaceStoreBuilderThat can beStoreConvert to aViewModelTo build the component tree, onceStoreIn theStateChange and you can rebuildStoreConnector).

inReduxthroughStoreStores state objects that represent the entire applicationState. Each application event (whether user-initiated or externally driven) is considered oneAction.ActionthroughReducerI schedule it, and thenReducerAccording to theActionTo update theStoreState in. And onceStoreState objects inStateChanged the corresponding viewViewIt will reflect the change in state. ReduxMost of the components can be decoupled, making it easier to refresh the UI. And the core business logic is thereReducerIn a function.ReducerTo receive aActionAnd the current state, and returns a new state object. So, to make unit testing easier, we just need to testReducerYou can test whether the state business logic is correct.

Redux middleware

This is just a first look at Redux, but what if you want to do something asynchronous, such as load data from an interface? This is where a new component, called Middleware, is introduced.

Middleware is the component that processes actions before the Reducer. It receives the current state object and the Action to be scheduled, and then runs the code (interface communication, data access, and so on). Ultimately, the middleware may continue to use the same Action, or a different Action, or even do nothing at all. With middleware, Redux’s flowchart looks like this:

In the code

Let’s take a simple counting application as an example to demonstrate the basic application of Redux. First we build Redux with three elements.

// counter_actions.dart, currently empty, business code can be added later
// The counter increases
class CounterAddAction {}
// The counter is reduced
class CounterSubAction {}

//counter_state.dart
class CounterState {
  int count = 0;

  CounterState(this.count);
}

// counter_reducer.dart
CounterState counterReducer(CounterState state, dynamic action) {
  if (action.runtimeType == CounterAddAction) {
    return CounterState(state.count + 1);
  }

  if (action.runtimeType == CounterSubAction) {
    return CounterState(state.count - 1);
  }

  return state;
}

Copy the code

As can be seen, core services are all in reducer. Reducer updates state according to action types and returns new state objects. Actions are dynamic and can be enumerations for simple operations, but objects are more convenient if you want to carry new data or business logic (for example, we can change how much we add or subtract with each click).

The Reducer definition of a Redux takes the old state and action parameters and returns the new state.

typedef Reducer<State> = State Function(State state, dynamic action)
Copy the code

Next comes the implementation of the page logic. The page logic is somewhat similar. If a Store needs to be used by lower-level components, it is defined in the higher-level component. Here we are relatively simple, directly defined in the current page can be. The key parts are the following:

  • buildIs used by a child component ofStoreProviderPackage for sharingstore.
  • Need to monitorstoreVariable component usageStoreConnectorbuilderBuild and can be usedconverterMethod will bestoreTo the data required by the component (that is, to the state dataViewModel), here we have simply converted the countString. inStoreConnectorMethod that notifies a refresh whenever a state object changes.
  • Button event: Executes the state object in the buttondispatchOperation in order to schedule correspondingreducerThe status update is complete.dispatchThe method is defined as follows, and you can actually seedispatchIs a set of schedules, and this is just the first method being called, which means that a series of scheduling operations can actually be performed.
dynamic dispatch(dynamic action) {
  return _dispatchers[0](action);
}
Copy the code
class CounterPage extends StatelessWidget {
  CounterPage({Key? key}) : super(key: key);
  final store =
      Store<CounterState>(counterReducer, initialState: CounterState(0));
  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Redux Counter'),
        ),
        body: Center(
          child: StoreConnector<CounterState, String>(
            converter: (store) => store.state.count.toString(),
            builder: (context, count) {
              return Text(
                count,
                style: TextStyle(color: Colors.blue, fontSize: 30)); }, ), ), floatingActionButton: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ FloatingActionButton( child: Icon(Icons.arrow_upward), onPressed: () { store.dispatch(CounterAddAction()); }), FloatingActionButton( backgroundColor: Colors.red, child: Icon( Icons.arrow_downward, ), onPressed: () { store.dispatch(CounterSubAction()); }), ], ), ), ); }}Copy the code

Running effect

The running effect is as follows.

conclusion

This paper introduces the basic concept of Redux and a simple example. Generally speaking, one of the advantages of using Redux is that the business model of the whole state management is consistent, which must have Action, Store and Reducer, so that the code structure can be indirectly regulated. The flutter_redux plugin also makes it easier to use Redux in Flutter.


This is a column about the entry and practice of Flutter. The corresponding source code is here: Entry and Practice of Flutter.

👍🏻 : feel the harvest please point a praise to encourage!

🌟 : Collect articles, easy to look back!

💬 : Comment exchange, mutual progress!