Skip to content

[go_router] Replace redirect with onEnter and onExit #102408

Open

Description

@johnpryan

In order to better support redirection, we should replace the redirection API with onEnter and onExit.

The onEnter function is called when the new location results in a RouteMatch that was not previously present on RouteMatchList:

matchList = [ "/a"]
matchList' = [ "/a", "b"]

When matchList changes to matchList', the onEnter callback for Route "b" will be called, and the callback for "/a" will not.

The onExit callback is invoked when the reverse is true:

matchList = [ "/a", "b"]
matchList' = [ "/a"]

When matchList changes to matchList', the onExit callback for Route "b" will be called.

Activity

  1. added
    c: new featureNothing broken; request for a new capability
    P3Issues that are less important to the Flutter project
    on Apr 22, 2022
  2. changed the title [-]Add hook for when routes are removed[/-] [+]Add onExit callback[/+] on Apr 22, 2022
  3. changed the title [-]Add onExit callback[/-] [+]Replace redirect with onEnter and onExit[/+] on Jul 22, 2022
  4. changed the title [-]Replace redirect with onEnter and onExit[/-] [+][go_router] Replace redirect with onEnter and onExit[/+] on Jul 22, 2022
  5. ElteHupkes commented on Sep 21, 2022

    @ElteHupkes

    Would it be possible to cancel / delay the route change through these callbacks? I feel like this could be a good mechanism to prevent route changes in case, for instance, a user has unsaved changes on the page you might want to warn them about.

  6. johnpryan commented on Sep 22, 2022

    @johnpryan
    ContributorAuthor

    Yes, onExit would support this scenario, similar to how you would use WillPopScope. (WillPopScope doesn't work with page-backed routes, which built by the Router / go_router)

  7. AceChen1 commented on Nov 25, 2022

    @AceChen1

    @chunhtai @johnpryan Hi guys, as we know, android app usually have a common requirement: when user on the root router, and then click the physical backward, will have a tips "click again to exist the app". previous navigator 1.0, i can use WillPopScope to listen & control the true/false to implement it, but i don't know how to implement it on the go router, any advice?

  8. otmi100 commented on Nov 30, 2022

    @otmi100

    Yes, onExit would support this scenario, similar to how you would use WillPopScope. (WillPopScope doesn't work with page-backed routes, which built by the Router / go_router)

    Is there any alternative to WillPopScope or a work-around? I'd love to warn my users that changes will be lost if he uses the Back-Button. Also I'd love to keep using go_router.

  9. johnpryan commented on Dec 1, 2022

    @johnpryan
    ContributorAuthor

    We will probably stick with redirect to avoid more breaking changes.

    @chunhtai also pointed out that this will require a framework change to make PopPageCallback asynchronous.

  10. subzero911 commented on Dec 21, 2022

    @subzero911

    +1 for onEnter / onExit methods in GoRoute.
    It will allow us to register dependencies right inside GoRoutes (and generally run any custom code)

    GoRoute(
            path: '/books',
            builder: (ctx, state) => BooksScreen(),
            onEnter: () => GetIt.I.registerSingleton<IBookController>(BookController());
            onExit: () => GetIt.I.unregister<IBookController>(disposingFunction: (controller) => controller.dispose());
    ),

    as proposed here: #99113 (comment)

    It's clean - you can open the routes.dart file and easily figure out, which screen uses which dependencies.
    And it gives you scopes - the registered controller could be read from all the child routes.

  11. 98 remaining items

  12. flutter-triage-bot commented on Jun 5, 2025

    @flutter-triage-bot

    The triaged-go_router label is irrelevant if there is no team-go_router label or fyi-go_router label.

  13. omar-hanafy commented on Oct 26, 2025

    @omar-hanafy

    Status update:
    Top-level onEnter shipped in go_router 16.3.0 (PR #8339). It lets apps intercept incoming navigation, implement deep-link handling without page renders, and decide push vs go semantics before legacy redirects and route-level redirects run.

  14. kerimamansaryyev commented on Dec 12, 2025

    @kerimamansaryyev

    Status update: Top-level onEnter shipped in go_router 16.3.0 (PR #8339). It lets apps intercept incoming navigation, implement deep-link handling without page renders, and decide push vs go semantics before legacy redirects and route-level redirects run.

    @chunhtai @omar-hanafy

    Unfortunately, the top level onEnter API does not fulfill the navigation prevention use-case (I followed up this issue from the Prevent Navigation topic of the package docs). Let me explain, while we can prevent from navigating from destination A to destination B, the prevention mechanism won't be executed in cascade. Here is an example:

    Here are the edge-cases:

    1. Suppose, we want to navigate from A/B/C to E/D/F, and underlying route B should have a navigation prevention mechanism but it won't be executed because the top-most route is C.
    2. Suppose, we want to navigate from A/B to A/B/C, and the underlying route B should have a navigation mechanism but it will be executed as false-positive, because although we navigate from A/B to A/B/C, B is not expected to be removed.

    The API that is the closest to implement navigation prevention in cascades is the onExit API but it still has this unresolved issue - #135909 , it requires disabling the swipe back gesture on iOS.

    React Native's react-navigation package has navigation prevention mechanism where the callbacks are executed in cascades, I am wondering if we could expect similar API from the Go Router in nearest future?

  15. added
    customer: crowdAffects or could affect many people, though not necessarily a specific customer.
    on Dec 18, 2025
  16. ThomasDuffinMears commented on Jun 11, 2026

    @ThomasDuffinMears

    So toplevel onEnter:

    • provides deeplinking support,
    • allows more complex navigation patterns.
    • evaluates only on route entry.

    And redirect:

    • stateful using refresh() or refreshListenable.
    • also evaluates during route entry.
    • limited support for deeplinking.

    Do I need to support both in my application? For instance, an authentication/onboarding flow may be triggered when an app launches via deeplink, but could also happen should a user logout or have their session expire. The former is best achieved with onEnter, but the latter can only be achieved with redirect. (IMO) the redirect pattern encourages string manipulation which is prone to error and even exploitation, and I'd rather use onEnter if I can, but the lack of statefulness makes that impossible for our use cases.

    Perhaps I can work on what is needed at a minimal level for both cases, but this is frustrating given the time spent trying to debug how the lifecycle changes work :(

  17. added a commit that references this issue on Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilitycustomer: crowdAffects or could affect many people, though not necessarily a specific customer.p: go_routerThe go_router packagepackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem team

    Type

    No type

    Projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions