24

I installed flutter_lints plugin in my project, after installing then it shows a warning message "Don't put any logic in createState". How to solve this issue?

class OverviewPage extends StatefulWidget {
  final int id;
  const OverviewPage({Key? key, required this.id}) : super(key: key);

  @override
  _OverviewPageState createState() => _OverviewPageState(id); // Warning on this line
}

class _OverviewPageState extends State<OverviewPage>{
  late final int id;
  _OverviewPageState(this.id);
}
Mohammed Nabil
  • 662
  • 1
  • 8
  • 36
  • 3
    Why you need that ? You can directly access that id in your state using widget.id, then why are you doing this ? – Midhun MP Dec 22 '21 at 08:11
  • 1
    Have you read [the documentation for the `no_logic_in_create_state` lint](https://dart-lang.github.io/linter/lints/no_logic_in_create_state.html)? – jamesdlin Dec 22 '21 at 08:13

4 Answers4

39

Don't pass anything to _OverviewPageState in the constructor.

class OverviewPage extends StatefulWidget {
  final int id;
  const OverviewPage({Key? key, required this.id}) : super(key: key);

  @override
  _OverviewPageState createState() => _OverviewPageState();
}

class _OverviewPageState extends State<OverviewPage>{
  // if you need to reference id, do it by calling widget.id
}
mmcdon20
  • 5,767
  • 1
  • 18
  • 26
  • 9
    Why is it bad to pass something in `_OverviewPageState()`? – Ali Akber Feb 08 '22 at 01:47
  • 1
    You can see the explanation for the lint here: https://dart-lang.github.io/linter/lints/no_logic_in_create_state.html – mmcdon20 Feb 08 '22 at 01:51
  • 7
    "Implementations of createState() should return a new instance of a State object and do nothing more" but why? I want to know why is this preferred? like what is the benefit? – Ali Akber Feb 08 '22 at 07:23
  • "Since state access is preferred via the widget field, passing data to State objects using custom constructor parameters should also be avoided and so further, the State constructor is required to be passed no arguments." - Ultimately lint rules are preferences for one coding style over another. If you follow this style you only have to declare each of the fields once rather than twice, and you only have to declare one constructor rather than two. – mmcdon20 Feb 08 '22 at 15:03
  • 4
    But I want to pass a default value to the State - and `widget.` cannot be accessed in the constructor. Is there a solution for setting default values for state values, other than `// ignore: no_logic_in_create_state` ? – kris May 03 '22 at 23:52
  • @kris you can provide a default value if for example you did `this.id = 0` instead of `required this.id`. You can also access `widget.` within the `@override initState() {...}` method of your `State<...>` class. – mmcdon20 May 04 '22 at 00:58
  • 3
    I'd like to learn if the bad approach has a memory concern or not rather than the stylistic concerns. – Eray Erdin Jun 07 '22 at 07:50
  • 1
    @mmcdon20 but if you access it through widget. you cannot edit the value, how would you update it? – Texv Nov 22 '22 at 00:46
  • Hello @ErayErdin. Long time gone and do you know what's the concerns except the stylistic concern? – 无夜之星辰 Apr 25 '23 at 08:33
6

I someone want to initiate a variable inside the state from the main class you can use for example, cause you can't use it in constructor class.

@override
void initState() {
    super.initState();
    id = widget.id;
    code = widget.code;
    //your code here
}
3

I guess that would be better to merge the two answer that you received.

@mmcdon20 is right, you don't have to pass any argument to the state constructor because, as @Mohamed stated, you can do that via the init_state using the widget argument or in the _OverviewPageState's constructor.

I am just doing the fusion of the answers here to be more precise for the ones who are new to Flutter.

The final result should look like this:

class OverviewPage extends StatefulWidget {
  final int id;
  const OverviewPage({Key? key, required this.id}) : super(key: key);

  @override
  _OverviewPageState createState() => _OverviewPageState();
}

class _OverviewPageState extends State<OverviewPage>{
  late int idCopy; 
  // the 'late' keyword is necessary because otherwise Flutter would expect
  // an initialization of the value from a Constructor that accept 'int id' 
  // as a parameter which is what we are trying to avoid because it's not the
  // correct path to follow when you initialize a State of StatefulWidget

  @override
  void initState() {
    super.initState();
    idCopy = widget.id;
    //your code here
  }
}

or, using the constructor

class _OverviewPageState extends State<OverviewPage>{
  late int idCopy; 
  
  _OverviewPageState() {
    idCopy = widget.id; // here it is :)
  }
}

Hope it clarify doubts for the newcomers :)

Credits: @Mohamed_Hammane, @mmcdon20

AndreP
  • 105
  • 1
  • 5
-1

Looking at the discussion above, the question revolves around the point that why is wrong to pass arguments inside createState. One thing which is clear is that the main reason for avoiding logic in createState is that it is called only once when the widget is first created. If you have any logic that depends on the widget's state or context, it may not behave as expected when the widget is reused or rebuilt.

For example, let's say you have a StatefulWidget that fetches data from an API in its createState method. If the widget is rebuilt because of a state change or navigation, the API call will not be made again because the createState method is not called again. This can result in stale or incorrect data being displayed.

Passing parameters to createState is not necessarily an issue. However, the avoid_logic_in_create_state lint rule suggests that you should avoid putting any logic in createState method for the reasons I mentioned earlier. To make it more holistic, virtually anything inside createState is not recommended and linter throws warning. Its important to note the linter works by validating a logic and as long as you do something in createState, that violates the logic.

Though it would be nice if flutter linter can get an upgrade and add this part.

Saurabh Kumar
  • 2,088
  • 14
  • 17