avoid-mounted-in-setstate

Path
lint/correctness/avoid-mounted-in-setstate
Default
Off, opt in
Origin
Falcon
Domain
flutter
Rule
90 of 512
flutter

Check mounted before invoking Flutter State.setState, never inside its callback. A check inside the callback cannot prevent setState's unmounted-State assertion. Deferred nested closures and local functions have independent mounted checks.

Invalid

example.dartdart
import 'package:flutter/material.dart' as f;
class S extends f.State<f.StatefulWidget> {
  int value = 0;
  void update(f.BuildContext other) {
    setState(() {
      if (mounted) value++;
    });
    this.setState(() {
      if (this.mounted) value++;
    });
    setState(() {
      if (context.mounted) value++;
    });
    setState((() {
      if (!other.mounted) return;
      value++;
    }));
    setState(() => value = mounted ? 1 : 0);
  }
}
class Child extends S {
  void inherited() {
    setState(() { if (mounted) value++; });
  }
}
Check `mounted` before calling `setState`, not inside its callback.
5 setState(() {
6 if (mounted) value++;
Check `mounted` before calling `setState`, not inside its callback.
8 this.setState(() {
9 if (this.mounted) value++;
Check `mounted` before calling `setState`, not inside its callback.
11 setState(() {
12 if (context.mounted) value++;
Check `mounted` before calling `setState`, not inside its callback.
14 setState((() {
15 if (!other.mounted) return;
Check `mounted` before calling `setState`, not inside its callback.
17 }));
18 setState(() => value = mounted ? 1 : 0);
Check `mounted` before calling `setState`, not inside its callback.
22 void inherited() {
23 setState(() { if (mounted) value++; });

Valid

example.dartdart
import 'dart:async';
import 'package:flutter/material.dart' as f;
class Flag { bool get mounted => true; }
class S extends f.State<f.StatefulWidget> {
  int value = 0;
  void subscribe(Stream<int> stream) {
    setState(() {
      stream.listen((event) {
        if (!mounted) return;
        value = event;
      });
      void later() {
        if (!context.mounted) return;
        value++;
      }
      value++;
    });
  }
  void update(f.BuildContext other, Flag flag) {
    if (mounted) setState(() { value++; });
    if (other.mounted) this.setState(() { value++; });
    if (!mounted) return;
    setState(() { value++; });
    setState(() {
      bool mounted = true;
      if (mounted) value++;
      if (flag.mounted) value++;
    });
    void setState(void Function() callback) { callback(); }
    setState(() { if (this.mounted) value++; });
  }
}
class Overridden extends S {
  bool get mounted => true;
  void updateFlag() { setState(() { if (mounted) value++; }); }
}
class Fake {
  bool mounted = true;
  void setState(void Function() callback) { callback(); }
  void update() { setState(() { if (mounted) return; }); }
}

Configure avoid-mounted-in-setstate

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-mounted-in-setstate": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/avoid-mounted-in-setstate: <reason>