auto_route_library icon indicating copy to clipboard operation
auto_route_library copied to clipboard

Race condition with guards when using router.pop() while reevaluating

Open jointhejourney opened this issue 1 year ago • 6 comments

Hey there,

Just to give context to the issue I found: I am utilizing reevaluateListenable to automatically update my guards when any of the user's information changes with a dialog that is behind a guard. However, I have noticed a race condition when you trigger a reevaluation and then immediately call `context.router.pop(); to close the dialog: the dialog closes and then opens up again rapidly.

This happens because:

  1. The user information is updated
  2. reevaluateListenable is triggered because of this (which starts the guard reevaluation)
  3. I manually call context.router.pop() to close the dialog
  4. The dialog is closed
  5. The guard completes it's reevaluation, and then calls resolver.next()
  6. Since resolver.next(); was called, the dialog opens again

I was wondering if there was a way to have context.router.pop() wait until current guards have been reevaluated before changing routes? Or perhaps abort the guard reevaluation to prevent it from calling resolver.next() if the route being reevaluated isn't in the stack anymore.

Happy to put together a MRE, but wanted to see if anyone had some ideas before I do it.

Thank you

jointhejourney avatar Jul 06 '23 22:07 jointhejourney

Hey @jointhejourney did you try doing something with NavigationResolver.isReevaluating?

Milad-Akarie avatar Aug 07 '23 07:08 Milad-Akarie

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Oct 06 '23 08:10 github-actions[bot]

I have this issue too

Here's my Guard

class AppGuard extends AutoRouteGuard {
  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    final BuildContext? context = router.navigatorKey.currentContext;

    optionOf(context).fold(
      () => resolver.next(),
      (context) {
        final bool isAppGuarded =
            context.read<SettingsCubit>().state.isAppGuarded;

        resolver.next();

        log('Does App Protected Now? $isAppGuarded');

        if (isAppGuarded && router.currentUrl == '/' ) {
          router.navigate(AppGuardRoute());
        }
      },
    );
  }
}

heshaShawky avatar Nov 05 '23 22:11 heshaShawky

Hey @jointhejourney did you try doing something with NavigationResolver.isReevaluating?

Hey there,

Just to give context to the issue I found: I am utilizing reevaluateListenable to automatically update my guards when any of the user's information changes with a dialog that is behind a guard. However, I have noticed a race condition when you trigger a reevaluation and then immediately call `context.router.pop(); to close the dialog: the dialog closes and then opens up again rapidly.

This happens because:

  1. The user information is updated
  2. reevaluateListenable is triggered because of this (which starts the guard reevaluation)
  3. I manually call context.router.pop() to close the dialog
  4. The dialog is closed
  5. The guard completes it's reevaluation, and then calls resolver.next()
  6. Since resolver.next(); was called, the dialog opens again

I was wondering if there was a way to have context.router.pop() wait until current guards have been reevaluated before changing routes? Or perhaps abort the guard reevaluation to prevent it from calling resolver.next() if the route being reevaluated isn't in the stack anymore.

Happy to put together a MRE, but wanted to see if anyone had some ideas before I do it.

Thank you

Ho did you fix this, I am facing the same issue along with a lot of other issues with reevaluate and guards

heshaShawky avatar Nov 06 '23 00:11 heshaShawky

Honestly, I just did a hacky workaround. I'm waiting 10 miliseconds which is enough time for the guards to re-evaluate. I haven't been able to get back to this and see if there's a way to prevent the race condition from happening.

Future.delayed(const Duration(milliseconds: 10), () {
  context.router.pop();
});

jointhejourney avatar Nov 08 '23 18:11 jointhejourney

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

github-actions[bot] avatar Dec 09 '23 08:12 github-actions[bot]