a variable is a final variable from a different page, Widget is Stateful, and I want to access it in initstate.
I can't use it directly or can access using another variable.
If the variable is final and defined on a different page, you won't be able to directly access it in the initState method of a Stateful widget. However, you may be able to access it indirectly by passing it as a parameter to the Stateful widget's constructor.
For example, you could define a constructor for your Stateful widget that takes the final variable as a parameter and then store that variable in the widget's state:
class MyWidget extends StatefulWidget {
final String myFinalVariable;
MyWidget({required this.myFinalVariable});
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String? myVariable;
#override
void initState() {
super.initState();
myVariable = widget.myFinalVariable;
}
// rest of your widget code...
}
Related
Currently, when I would like initial values of a stateful widget to be configurable, I follow a pattern that looks like
class MyWidget extends StatefulWidget {
final String? initialValue;
MyWidget({ this.initialValue });
#override State createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
String statefulValue = "default initial value";
#override
void initState() {
super.initState();
if (widget.initialValue != null) { statefulValue = widget.initialValue; }
}
// ...
}
This works, but seems a bit heavyweight to me to achieve something I have to think is a very common use case. First, it doesn't make sense to me that initialValue should have to be a field at all, since its use is only to initialize the state, and then is no longer needed. Second, I think it would avoid some boiler plate if the state class could have a constructor that the stateful widget could call, so the above could look like:
class MyWidget extends StatefulWidget {
final String? initialValue;
MyWidget({ this.initialValue });
#override State createState() => MyWidgetState(initialValue: initialValue);
}
class MyWidgetState extends State<MyWidget> {
String statefulValue;
MyWidgetState({ String? initialValue }) : statefulValue = initialValue ?? "default initial value";
// ...
}
That doesn't exactly solve the first problem, but I think reads more easily. This however triggers the "Don't put any logic in createState" linter error. So my questions are
a) is there a pattern where the initial value doesn't have to be held on to longer than necessary?
b) why is passing parameters to the State constructor frowned upon?
You can provide default value on constructor
class MyWidget extends StatefulWidget {
final String initialValue;
const MyWidget({this.initialValue = "default initial value"});
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late String statefulValue = widget.initialValue;
When creating a stateful widget in flutter, you may want some fields of the widget to not be mutated. In that case, I'm having trouble trying to figure out if it is better to always reference those fields from the state's widget reference, or if it's better to declare those fields in the state still, and get any initial values from the widget. For example:
class MyStatefulWidget extends StatefulWidget {
final bool? mutateMe; // allows the user to provide an initial value of a mutable field
final bool? doNotMutateMe; // allows the user to provide the value of a field that is not intended to be mutated
MyStatefulWidget({ super.key, this.mutateMe, this.doNotMutuateMe });
#override State<MyStatefulWidget> createState() => MyStatefulWidgetState();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
late bool mutateMe;
late bool doNotMutateMe; // <-- HERE: is it better to include this field here?
#override void initState() {
mutateMe = widget.mutateMe ?? true;
doNotMutateMe = widget.doNotMutateMe ?? false;
}
// ...
}
For a field like doNotMutateMe, that is not intended to be modified, does it make sense to re-create the field in the state object, or not, and always just refer to widget.doNotMutateMe instead?
I've read that the state object outlives the widget, so I'm curious what implications that might have here?
As you've included , I will prefer using widget.variableName on state class
class MyStatefulWidget extends StatefulWidget {
final bool? mutateMe;
final bool? doNotMutateMe;
const MyStatefulWidget({
super.key,
this.mutateMe = true,
this.doNotMutateMe = false,
});
#override
State<MyStatefulWidget> createState() => MyStatefulWidgetState();
}
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.
I am trying to pass a User object from my stateful widget, to its state.
class NavBar extends StatefulWidget {
final User user;
NavBar({this.user});
#override
NavBarState createState() => NavBarState();
}
class NavBarState extends State<NavBar> {
int _currentIndex = 0;
final List<Widget> _children = [
CalendarWidget(),
HomeWidget(),
MessagingWidget(),
ProfilePage(user: user)
];
Widget build(BuildContext context) {
All other solutions say to use widget.user like ProfilePage(user: widget.user) but that throws error:
Only static members can be accessed in initializers.dart(implicit_this_reference_in_initializer)
How can I access User object in the state of NavBar so I can send it to ProfilePage()?
you can use widget.yourObjectsName to access StateFul widget's Object in its state
you can use any property of Stateful Widgets from its state by widget property of state which gives reference to state's Widget properties.
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.