1

I'm still learning Flutter, and lately trying many Redux tutorials. I have gotten through many samples with counter, firebase auth, and cloud firebase. Here's an example app from http://flutterbyexample.com/ that I will base my question on. Here's what I want to do:

  1. User presses login button
  2. Login button is disabled/replaced with progress indicator
  3. Middleware performs API call to login
  4. Login succeeds or fails
  5. Progress indicator is replaced by logout button

The issue I am noticing is that currently the login/logout button can be pressed multiple times quickly and may appear buggy when I perform the login API call on the action dispatched by the button.

Without redux I would track the button with a boolean in the state widget and use the built in FutureBuilder to replace the button immediately after the button is pressed.

I tried to implement this behavior with a boolean isLoading in my Redux store. But when I try to dispatch additional actions I end up in an infinite loop or it doesn't fire at all, so I don't know where to dispatch the actual API login action.

I believe my question is similar to this stackoverflow question but I don't know how the answer can be applied in Flutter.

  • Not sure what your use case is but login can be an explicit action initiated by the user (presses button). I wouldn't use a middleware for that (unless multiple actions need to trigger a login request). When it reaches the reducer you toggle isLoading to true immediately, like you described. This in turn is used to disabled the login button or replace it with a loading indicator. The success action then lets the state reflect that the user is logged in and nothing is loading anymore. What do you mean by "dispatch additional actions"? – timotgl Apr 21 '18 at 09:06
  • What I meant by dispatch additional actions is I had a series of actions Login->LoginStart->Login Success/Fail. I wanted to dispatch the intermediate action LoginStart after the user pressed the button and before middleware call. Sorry I didn't clarify what the current flow is for my example. The user presses button, login action is dispatched, middleware is used to authenticate using firebase_auth, the middleware also then fires the login success or fail action. If I don't use a middleware for authentication could you describe where that would go? Thank you! – user9225839 Apr 21 '18 at 17:10
  • Right, yes, the async login action is actually request -> success/failure. Important for handling loading state and error messages etc. – timotgl Apr 21 '18 at 22:37

1 Answers1

2

I found the missing piece! redux is for synchronous actions, in order to add asynchronous behavior redux_thunk can be used to wrap the actions with a function call.

Redux provides a simple way to update a your application's State in response to synchronous Actions. However, it lacks tools to handle asynchronous code. This is where Thunks come in.

// Create a `ThunkAction`, which is any function that accepts the 
// Store as it's only argument. Our function (aka ThunkAction) will
// simply send an action after 1 second.  This is just an example, 
// but  in real life, you could make a call to an HTTP service or 
// database instead!
final action = (Store<String> store) async {
  final searchResults = await new Future.delayed(
    new Duration(seconds: 1),
    () => "Search Results",
  );

  store.dispatch(searchResults);
};