Skip to main content

How does a guard wait for facts it does not know yet?

Signing in can finish before the profile arrives. A guard that reads an unknown role as permission to proceed builds the destination, then redirects once the profile loads. That produces a frame of a page the person should never have seen.

DwDecisionGuard returns DwGuardDecision.allow, .redirect(path) or .pending. Unknown router-state fields are nullable; a guard reading one handles null explicitly with pending. The example's admin zone waits for the role:

(state, _) => switch (state.role) {
null => DwGuardDecision.pending,
UserRole.admin => DwGuardDecision.allow,
_ => DwGuardDecision.redirect(AppNavigationZone.schedule.fullPath),
},

This is in example/dartway_example_flutter/lib/core/router/navigation_zones/admin_navigation_zone.dart. The preceding sign-in guard redirects a signed-out person before checking the role. Guards decide in order; allow continues, redirect or pending ends that evaluation.

The app supplies one loading page through DwGoRouterOptions.pendingBuilder. While pending, the router builds that page in place of the target, inside the zone's unchanged shell. The URL stays the same, no extra history entry appears, and the target's widget never builds. When the router-state provider changes, guards run again and the allowed page or redirect replaces loading. A pending answer without a loading builder fails with an error naming the missing option.

Each retained page checks its own route and target, even when a public page is pushed above it. A pushed pending destination executes its redirect when the guard resolves.

A test can import package:dartway_router/testing.dart and call dwCheckPendingGuards with all zones, representative known states and a setter for every nullable field. Each setter returns the state with that field null; Dart records cannot enumerate fields at runtime. The helper fails if a guard allows an unknown value where the corresponding known value redirects. Supply concrete targets for parameterized or query-sensitive guards. A widget regression checks that the destination's build counter stays zero through loading and redirect.