use_build_context_synchronously

Stable
Flutter

Do not use BuildContext across asynchronous gaps.

Details

#

DON'T use BuildContext across asynchronous gaps.

Storing BuildContext for later usage can easily lead to difficult-to-diagnose crashes. Asynchronous gaps are implicitly storing BuildContext and are some of the easiest to overlook when writing code.

When a BuildContext is used, a mounted property must be checked after an asynchronous gap, depending on how the BuildContext is accessed:

  • When using a State's context property, the State's mounted property must be checked.
  • For other BuildContext instances (like a local variable or function argument), the BuildContext's mounted property must be checked.

BAD:

dart
void onButtonTapped(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 1));
  Navigator.of(context).pop();
}

GOOD:

dart
void onButtonTapped(BuildContext context) {
  Navigator.of(context).pop();
}

GOOD:

dart
void onButtonTapped(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 1));

  if (!context.mounted) return;
  Navigator.of(context).pop();
}

GOOD:

dart
abstract class MyState extends State<MyWidget> {
  void foo() async {
    await Future.delayed(const Duration(seconds: 1));
    if (!mounted) return; // Checks `this.mounted`, not `context.mounted`.
    Navigator.of(context).pop();
  }
}

Enable

#

To enable the use_build_context_synchronously rule, add use_build_context_synchronously under linter > rules in your analysis_options.yaml file:

analysis_options.yaml
yaml
linter:
  rules:
    - use_build_context_synchronously

If you're instead using the YAML map syntax to configure linter rules, add use_build_context_synchronously: true under linter > rules:

analysis_options.yaml
yaml
linter:
  rules:
    use_build_context_synchronously: true