title: flutter: wait for the navigation transition to end
body: <p>I have a kinda special use-case which is giving me headaches for hours now.</p>
  
  <p>I do have an application which is using firebase and social logins for authentication. Additionally I implemented redux to manage the apps state.</p>
  
  <p>Everything is working fine like this, but only when I try to logout while on a screen which needs data from the <code>FirebaseUser</code> class the rendering will fail, because the transition of the navigator is still running (triggers a rerendering of the screen I am navigating away from) and finally ends up in the desired place, but with a faulty screen while transitioning.</p>
  
  <p>My middleware code for this is this:</p>
  
  <pre class="lang-dart prettyprint-override"><code>Middleware&lt;RootState&gt; _signOutUser(GlobalKey navigatorKey) {
    return (Store&lt;RootState&gt; store, dynamic dynamicAction, NextDispatcher next) {
      final SignOut action = dynamicAction;
      final NavigatorState nav = navigatorKey.currentState;
  
      next(action);
  
      store.dispatch(AppIsLoading());
  
      Future&lt;dynamic&gt;(() async {
        try {
          await auth.signOut();
        } on PlatformException catch (error) {
          return Future&lt;void&gt;.error(error);
        }
      }).then&lt;void&gt;((dynamic _) {
        nav.pushNamedAndRemoveUntil(Routes.home, (Route&lt;dynamic&gt; route) =&gt; false);
        store.dispatch(UnsetUser());
        store.dispatch(AppIsLoaded());
        action.completer.complete();
      }).catchError((Object response) {
        nav.maybePop(nav.context);
        action.completer.completeError(response);
        store.dispatch(AppIsLoaded());
      });
    };
  }
  </code></pre>
  
  <p>I would ideally do it like this:</p>
  
  <pre class="lang-dart prettyprint-override"><code>Middleware&lt;RootState&gt; _signOutUser(GlobalKey navigatorKey) {
    return (Store&lt;RootState&gt; store, dynamic dynamicAction, NextDispatcher next) {
      final SignOut action = dynamicAction;
      final NavigatorState nav = navigatorKey.currentState;
  
      next(action);
  
      store.dispatch(AppIsLoading());
  
      Future&lt;dynamic&gt;(() async {
        try {
          await auth.signOut();
        } on PlatformException catch (error) {
          return Future&lt;void&gt;.error(error);
        }
      }).then&lt;void&gt;((dynamic _) {
        return nav.pushNamedAndRemoveUntil(Routes.home, (Route&lt;dynamic&gt; route) =&gt; false);
      }).then&lt;void&gt;((dynamic _) {
        store.dispatch(UnsetUser());
        store.dispatch(AppIsLoaded());
        action.completer.complete();
      }).catchError((Object response) {
        nav.maybePop(nav.context);
        action.completer.completeError(response);
        store.dispatch(AppIsLoaded());
      });
    };
  }
  </code></pre>
  
  <p>But this way as well, the rendering while transitioning takes place.</p>
  
  <p>I could just add guards to the screen, but that would result in a screen that is not looking like the one i was just viewing.</p>
  
  <p>Or is there a way inside the widget to prevent re-rendering at a special event, so that it just stays the way it was?</p>
  
  <p>I am kinda lost atm, so any help is appreciated.</p>
  
  <p>Thanks!</p>