Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: no_logic_in_state_constructor #3059

Closed
5 tasks done
goderbauer opened this issue Nov 11, 2021 · 7 comments · May be fixed by #3138
Closed
5 tasks done

proposal: no_logic_in_state_constructor #3059

goderbauer opened this issue Nov 11, 2021 · 7 comments · May be fixed by #3138
Labels
lint-proposal needs-info Additional information needed from the issue author P3 A lower priority bug or feature request status-pending

Comments

@goderbauer
Copy link
Contributor

no_logic_in_state_constructor

Description

The constructor of a State object should never contain any logic. That logic should always go into State.initState. When people put this kind of logic into their constructor, they often run into trouble.

Kind

Guard against errors.

Good Examples

class FooState extends State<Foo> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
  super.initState();
  _controller = AnimationController(vsync: this);
  }
  // ...
}

Bad Examples

class FooState extends State<Foo> with SingleTickerProviderStateMixin {
  FooState() {
   _controller = AnimationController(vsync: this);
  }

  late AnimationController _controller;

  // ...
}

Discussion

Add any other motivation or useful context here.

Discussion checklist

  • List any existing rules this proposal complements, overlaps or conflict with.
  • List any relevant issues (reported here, the SDK Tracker, or elsewhere).
  • If there's any prior art (e.g., in other linters), please add references here.
  • If this proposal corresponds to Effective Dart or Flutter Style Guide advice, please call it out. (If there isn’t any corresponding advice, should there be?)
  • If this proposal is motivated by real-world examples, please provide as many details as you can. Demonstrating potential impact is especially valuable.

/cc @dnfield

@dnfield
Copy link

dnfield commented Nov 11, 2021

I wonder if we can/should also lint that you don't otherwise initialize variables in State objects, e.g.

class FooState extends State<Foo> {
  // Should be initializing this in initState rather than here
  final MySpecialControllerThatDoesNotNeedThis _controller = MySpecialControllerThatDoesNotNeedThis(bar: 3);

  ...
}

@goderbauer
Copy link
Contributor Author

That seems overly limiting. It's totally fine (and common) to initialize a TextEditingController like that, for example.

@dnfield
Copy link

dnfield commented Nov 11, 2021

Maybe if it's late final but if it's final you might be initializing an object you'll never use right?

@bwilkerson
Copy link
Member

What does the word "logic" mean in this context? The proposed implementation flags constructors whose body is not empty, implying that no code should be executed when an instance is created, but that appears to conflict with the claim that it's acceptable to initialize a TextEditingController (though if it's only late final fields that can have initializers, then that would be consistent with not executing code when the instance is created).

@minhqdao
Copy link
Contributor

minhqdao commented Jan 22, 2022

I don't think there are any actual conflicts, but I agree that we could be a little bit more specific with what we mean by "logic executed at instance creation". Maybe we should mention that initializations, such as creating instances of a TextEditingController (which is ultimately logic being executed when an instance of a State is created), should be performed in initState or defined in conjunction with the declaration of its respective member, while all other code should be executed in initState.

BAD:

class FooState extends State<Foo> with SingleTickerProviderStateMixin {
  FooState() {
    // It's best if you don't do anything here
    _animationController = AnimationController(vsync: this);
    _textEditingController = TextEditingController();
    _myMethod();
  }

  late final AnimationController _animationController;
  late final TextEditingController _textEditingController;
  // ...
}

Good:

class FooState extends State<Foo> with SingleTickerProviderStateMixin {
  // Declare members here
  late final AnimationController _animationController;
  late final TextEditingController _textEditingController;

  @override
  void initState() {
    super.initState();
    // Initialize members and execute all other code here
    _animationController = AnimationController(vsync: this);
    _textEditingController = TextEditingController();
    _myMethod();
  }
  // ...
}

Good:

class FooState extends State<Foo> with SingleTickerProviderStateMixin {
  // Declare and initialize members here
  late final AnimationController _animationController = AnimationController(vsync: this);
  final TextEditingController _textEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();
    // Execute all other code here
    _myMethod();
  }
  // ...
}

Bottom line is that logic executed at creation of a State instance is fine. But it shouldn't happen in the constructor body because that often doesn't go well with the rest of the State lifecycle.

@srawlins
Copy link
Member

srawlins commented Oct 4, 2022

Is the proposal here that a State constructor should not even have a body? Or is it a set of statements that should be banned, like assignments, method calls, ...

@srawlins srawlins added the P3 A lower priority bug or feature request label Oct 4, 2022
@srawlins srawlins added the needs-info Additional information needed from the issue author label Apr 17, 2023
@github-actions
Copy link

github-actions bot commented May 1, 2023

Without additional information we're not able to resolve this issue, so it will be closed at this time. You're still free to add more info and respond to any questions above, though. We'll reopen the case if you do. Thanks for your contribution!

@github-actions github-actions bot closed this as completed May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lint-proposal needs-info Additional information needed from the issue author P3 A lower priority bug or feature request status-pending
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants