Skip to content

Conversation

@berlisB
Copy link

@berlisB berlisB commented Jan 26, 2026

go_router_builder: generate onEnter callback
go_router_builder: add tests for onEnter generation

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue.

Description

This PR adds support for route-level onEnter navigation guards in GoRouteData classes for go_router_builder.

What changed

go_router:

  • Added EnterCallback typedef for route-level onEnter callbacks
  • Added onEnter parameter to GoRoute constructor
  • Added onEnter method to _GoRouteDataBase with default Allow() implementation
  • Updated _GoRouteParameters to include onEnter callback
  • Modified GoRouteData.$route() and RelativeGoRouteData.$route() helpers to pass onEnter to generated routes

go_router_builder:

  • Added test case on_enter.dart demonstrating usage of onEnter in GoRouteData classes
  • Code generation automatically handles onEnter method through existing $route() helper infrastructure

Why

Resolves issue #181471

Currently, go_router 16.3.0 introduced a global onEnter callback at the GoRouter level. However, there's no way to define route-specific navigation guards in GoRouteData classes, unlike redirect and onExit which work at the route level.

This PR enables developers to override the onEnter method in their GoRouteData classes to implement navigation guards for specific routes, providing consistency with the existing onExit pattern.

Example Usage

@TypedGoRoute<ProtectedRoute>(path: '/protected')
class ProtectedRoute extends GoRouteData {
  @override
  FutureOr<OnEnterResult> onEnter(
    BuildContext context,
    GoRouterState current,
    GoRouterState next,
    GoRouter router,
  ) {
    final isAuthenticated = checkAuth();
    if (!isAuthenticated) {
      return Block.then(() => router.go('/login'));
    }
    return const Allow();
  }

  @override
  Widget build(BuildContext context, GoRouterState state) {
    return const ProtectedScreen();
  }
}

Note on Implementation Status

⚠️ Important: This PR implements the API surface and code generation, but the routing infrastructure to call GoRoute.onEnter during navigation is not yet implemented. The generated code is correct, but the callback won't be invoked until the routing logic in parser.dart is updated to handle route-level onEnter callbacks (similar to how onExit is handled in delegate.dart).

This PR can serve as a foundation, but additional work is needed to complete the feature.

Fixes #181471

Tests

  • All 389 existing tests in go_router pass
  • All 40 tests in go_router_builder pass (including new on_enter.dart test case)
  • New test file: packages/go_router_builder/test_inputs/on_enter.dart and .expect file

Version Updates

  • Updated CHANGELOG.md for both go_router and go_router_builder
  • Version bumps should be handled by repository maintainers using the standard tooling

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

go_router_builder: generate onEnter callback
go_router_builder: add tests for onEnter generation
@berlisB berlisB requested a review from chunhtai as a code owner January 26, 2026 15:11
@github-actions github-actions bot added p: go_router_builder p: go_router triage-framework Should be looked at in framework triage labels Jan 26, 2026
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces route-level onEnter navigation guards for GoRouteData classes in go_router and go_router_builder. This feature allows developers to implement specific navigation guards for individual routes, aligning with the existing onExit pattern. The changes include adding an EnterCallback typedef, an onEnter parameter to the GoRoute constructor, and an onEnter method to _GoRouteDataBase with a default implementation. The go_router_builder has been updated to generate the onEnter callback, and new test cases demonstrate its usage. It's important to note that while the API surface and code generation are implemented, the routing infrastructure to invoke GoRoute.onEnter during navigation is not yet part of this PR and will require further updates to parser.dart.

- [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
- [x] I read the [Tree Hygiene] page, which explains my responsibilities.
- [x] I read and followed the [relevant style guides] and ran [the auto-formatter].
- [ ] I signed the [CLA].

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The "I signed the [CLA]." checkbox is unchecked. Please ensure the Contributor License Agreement (CLA) is signed before merging this pull request.

// https://github.com/flutter/flutter/issues/171410
import 'package:meta/meta.dart' as meta;

import '../go_router.dart';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The import ../go_router.dart seems redundant here. Typically, go_router.dart re-exports its public APIs, and specific files like configuration.dart, match.dart, on_enter.dart, etc., are imported directly. Importing the top-level library might lead to unnecessary dependencies or potential circular imports if not carefully managed. Please consider removing this import if all necessary symbols are already imported from their specific files.


*List which issues are fixed by this PR. You must list at least one issue.*

## Description
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is used for all pull request, we shouldn't change it. Can you revert this change?

);
}

// (Moved) Route-level onEnter handling is implemented as an instance method
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does the (moved) mean in the context of this doc?

if (routeLevelBlocked != null) {
// A route-level onEnter blocked navigation; treat as blocked.
matchList = routeLevelBlocked;
_resetRedirectionHistory();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we reset history here?


// Iterate in the same visitation order and invoke onEnter sequentially.
for (final RouteMatchBase match in routeMatches) {
if (!context.mounted) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if context is not mounted, we should just abort the entire navigation


if (onEnterResult is Block) {
// When a route-level onEnter blocks, run onCanNotEnter to get final match list.
final OnEnterThenCallback? thenCb = onEnterResult.then;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should avoid uncommon abbreviation

Suggested change
final OnEnterThenCallback? thenCb = onEnterResult.then;
final OnEnterThenCallback? thenCallback = onEnterResult.then;

/// - [current]: The current route state
/// - [next]: The route state being navigated to
/// - [router]: The GoRouter instance
typedef EnterCallback =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already an OnEnter typedef

…type and improve navigation state reset logic and unmounted context handling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p: go_router_builder p: go_router triage-framework Should be looked at in framework triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants