PopScope: Guarding Your Flutter Routes
PopScope acts as a gatekeeper for back navigation in Flutter, letting you intercept and block attempts to leave a screen. Use it to show a confirmation dialog for unsaved changes. Its behavior differs on iOS; the swipe-back gesture won't trigger its callback.
WHY IT EXISTS Apps often need to control when a user can leave a screen. Without a mechanism to intercept back navigation, a user might accidentally discard unsaved data or interrupt a crucial process just by hitting the back button or using a back gesture. PopScope provides a standard API to manage this user flow.
THE MENTAL MODEL Think of PopScope as a bouncer at a club's exit. You wrap your page's content in it. When a user tries to leave, the bouncer (PopScope) checks its rules (the canPop property). If the rules allow it, the user leaves. If not, the bouncer stops them but still reports the attempt via the onPopInvokedWithResult callback.
HOW IT WORKS You wrap a widget tree with PopScope and control its behavior with two main properties. First, canPop: when set to false, it blocks the current route from being popped. Second, onPopInvokedWithResult: a callback that fires after a pop is attempted, telling you whether the navigation was successful (didPop) and providing any result data. This mechanism intercepts both system back gestures and programmatic calls like Navigator.pop().
WHEN TO USE IT The primary use case is preventing accidental data loss. Wrap a form page in a PopScope to check if there are unsaved changes. If so, you can set canPop to false and use the callback to trigger a confirmation dialog. It's also useful for blocking navigation during critical, uninterruptible operations like a file upload.
WHEN NOT TO USE IT For simple cases with nested Navigators, the less verbose NavigatorPopHandler might be a better choice. For forms specifically, Form.canPop and Form.onPopInvokedWithResult offer a more integrated solution. Don't use PopScope just to run cleanup code; use other widget lifecycle methods for that.
ONE CANONICAL EXAMPLE The key footgun is platform-specific behavior. On Android, if canPop is false, a system back gesture is blocked, but onPopInvokedWithResult is still called with didPop: false. On iOS, the swipe-to-go-back gesture is handled by Flutter, not the OS. If canPop is false, this gesture is completely ignored, and onPopInvokedWithResult is not called at all. This can lead to inconsistent UX if not handled explicitly.
Read the original → api.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.