The member 'setState' can only be used within instance members of subclasses of 'package:flutter/src/widgets/framework.dart' - flutter

(i18n) I use setState from outside of MyApp class to change language, I got this warning, and don't know how to solve it.
info: The member 'setState' can only be used within instance members of subclasses of 'package:flutter/src/widgets/framework.dart'. (invalid_use_of_protected_member at [flutter_firebase_authen] lib\app.dart:22)
class MyApp extends StatefulWidget {
final FirebaseAnalyticsObserver observer;
const MyApp({
Key key,
#required this.observer,
}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
static void setLocale(BuildContext context, Locale newLocale) {
final _MyAppState state = context.ancestorStateOfType(const TypeMatcher<_MyAppState>());
state.setState(() {
state.locale = newLocale;
});
}
}

The warning message is quite clear: the function setState should only be called from within the class, not from another class.
The workaround is simple, write a helper function inside your State class, that calls setState for you. For example:
refresh() => setState(() {});
Now from outside this class, you can call state.refresh().
(But really, if you are calling setState from another class, maybe you should look into ValueNotifier, or StreamBuilder, etc.)

Related

createState function creates a mutable state in Flutter

createState:
Creates the mutable state for this widget at a given location in the tree.
https://api.flutter.dev/flutter/widgets/StatefulWidget/createState.html
Now, in code:
class A extends StatefulWidget {
#override
_AState createState() => _AState();
}
class _AState extends State<A> {
}
Here we create a separate class named _AState which inherits from a predefined class named State?
So, what is createState' role here? How does it create a mutable state for us?
With createState you tell the StatefulWidget which class to use as state for this widget. And you tell it here that it needs to create an instance of _AState for this widget.
By the way, it is also recommended to write it as
State<A> createState() => _AState();
It still works the way you wrote it but the IDE might complain about
Avoid using private types in public APIs
Saying the return type is State<A> instead of _AState removes this warning.
In order to create a stateful widget in a flutter, it uses the createState() method. Stateful Widget means a widget that has a mutable state.

Initialize StatefulWidget state null safe from widget constructor in Flutter

I want to have a StatefulWidget where I can pass the initial value for a non-nullable member of the widgets State from the widgets constructor.
My current solution (see below) seems to be not ideal, I see two problems with it:
The initial value has to be saved in the widget itself before passing it to the state.
The member in the sate has to be marked as late since it can only be set after initialization.
Is there a better way to initialize a StatefulWidget's state non-nullable member from a value passed to the widget constructor?
My current implementation:
class MyWidget extends StatefulWidget {
final String text;
const MyWidget({Key? key, required this.text}) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late String text;
#override
void initState() {
text = widget.text;
super.initState();
}
#override
Widget build(BuildContext context) {
return Text(text);
}
}
(Not shown here, but later the text member should be changeable, that's why it is in the State)
hey there your code seems good.
but the better way is using bloc to pass and receive data.
any way . its not necessary to pass and fill data in initstate and _MyWidgetState .
you can receive your data directly in build widget As you wrote (widget.text)
here is some good things for avoid nullable
https://codewithandrea.com/videos/dart-null-safety-ultimate-guide-non-nullable-types/
You could use the constructor of State like this: _MyWidgetState(){ text=widget.text; }. The constructor will certainly be executed before initState and build methods.

Using widget property VS taking arguments on state class

Given a stateful widget which takes arguments when it's called, there are two options (that I know of).
I can either use widget.arg to access the data in the state object, or I can create new variables and a new constructor in the state object.
Now I've mostly used the second one and there are some use cases in which the first one causes some problems. However, it looks more concise and readable (I guess).
My question is which one is a better practice?
Example code:
First option:
class Home extends StatefulWidget {
final String email;
const Home({Key key, this.email}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
String example() {
return widget.email;
}
Second option:
class Home extends StatefulWidget {
final String email;
const Home({Key key, this.email}) : super(key: key);
#override
_HomeState createState() => _HomeState(email);
}
class _HomeState extends State<Home> {
final String email;
_HomeState(this.email);
String example() {
return email;
}
I use both approaches, however, i don't use a constructor for the second approach because idk i don't like it. I store a reference in initState. Something like email = widget.email;.
It really depends. It's mostly preference. But i use the widget. approach often, it avoids boilerplate code, and it's a way of identifying which arguments come from the widget vs whcih arguments come from the state.
The flutter team also uses this approach. A LOT. Check the Material AppBar source code. It would be a mess to declare the arguments twice and pass them to _AppBarState. It's cleaner and it works for them. And for me ;)
Don't use the second option, aka having a constructor on State. This is a bad practice.
Use the .widget.property syntax instead.
If you purposefully want to ignore the updates of a property, instead use initState:
class Example {
Example(this.initialText);
final String initialText;
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
String text;
#override
void initState() {
text = widget.initialText;
}
}

Access member of State from instance of Stateful Widget

I have StatefulWidget instance.
However I want to access the method of State from the instance of StatefulWidget.
It might be very simple and basic for flutter, but for the beginner of Stateful/State systen, it is a bit complex.
class MainBody extends StatefulWidget{
#override
_MainBodyState createState() => _MainBodyState();
}
class _MainBodyState extends State<MainBody>{
_MainBodyState();
void connectMainBody(){
print("ConnectMainBody");
}
class _MyHomePageState extends State<MyHomePage> {
Widget mainBody;
#override
void initState() {
super.initState();
mainBody = new MainBody();
mainBody.connectMainBody()// how can I access this method??
}
My idea was completely wrong.
https://medium.com/flutter-community/flutter-communication-between-widgets-f5590230df1e
I checked this page and learned.
How to access from Parent to Child.
By giving parameters to Child's Constructor.
How to access from Child to Parent.
By using callback function given to Child from Parent in advance.
I think I should learn about GlobalKey next.
Thank you very much for your advice.

Flutter state outside State object

I keep primitive states inside State. But for objects, the following works:
class _Like extends StatefulWidget {
final Post _post; <-- mutable object is here
_Like(this._post);
#override
State<StatefulWidget> createState() => _LikeState();
}
class _LikeState extends State<_Like> {
...
_like() {
setState(() {
widget._post.liked = !widget._post.liked; <-- mutated here
});
}
...
}
What would the be reason not to use this approach? (As opposed to moving the state inside State, preferably as primitive bool)
Perhaps because initState() is in the State class, which your StatefulWidget can't call. So your entire state should be in your State class to permit that.