Flutter: Undefined name Try correcting the name to one that is defined, or defining the name - flutter

I am facing a few strange issues with Flutter. I do have very little knowledge about Flutter. I am learning it.
class ViewOtherProfile extends StatefulWidget {
final String userName;
final int points;
const ViewOtherProfile({
#required this.userName,
#required this.points,
});
You can see i am getting userName and Points data as argument.
I want to print this argument in the page. Like this
class _ViewOtherProfileState extends State<ViewOtherProfile> {
..........
void initState(){
print(points);
deviceInfo();
super.initState();
print(userName);
]);
}
............
Now problem is i am getting error.
Undefined name 'userName'.
Try correcting the name to one that is defined, or defining the name.
Any reason why i am getting this error and how i can resolve it.
Thanks to #jamesdlin
I tried to put it like this
print(ViewOtherProfile.userName);
but now i am getting another error.
Instance member 'userName' can't be accessed using static access.

There are two main types of widgets in Flutter. StatelessWidget and StatefullWidget. A StatelessWidget is built only one when the UI builds and is never rebuilt. Meanwhile, a StatefulWidget can be rebuilt every time if a call for setState is made.
Hence, for a StatefulWiget, there is a need to track the state of the class by extending the main class with a State class.
You have to note that the scope of variables in those two types of widgets can vary. For example...
class ExampleStateless extends StatelessWidget {
final String userName;
final int points;
const ExampleStateless({
#required this.userName,
#required this.points,
});
#override
Widget build(BuildContext context){
print(userName); print(points);
return Something();
}
}
Note that for the stateful widget, there are two classes and each class has its scope. The superclass ExampleStateful can share its scope to its subclass _ExampleStatefulState via the widget
class ExampleStateful extends StatefulWidget {
final String userName;
final int points;
Static final string id = "exampleState";
const ExampleStatefull({
#required this.userName,
#required this.points,
});
// scope 1
#override
_ExampleStatefulState createState() => _ExampleStatefulState();
}
class _ExampleStatefulState extends State<ExampleStateful>{
// scope 2
final String userName2 = null;
#override
void initState(){
super.initState();
print(widget.userName);
print(userName2);
print(ExampleStateful.id); // you can do this only if variable is static.
}
}
What is in scope 1 can be accessed in scope 2 via the widget properties. eg print(widget.userName); instead of print(userName);

Related

Initializing non-mutable fields in Stateful Widgets in Flutter

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();
}

Accessing state in widget and making class immutable

I need to expose a couple of functions of a Stateful Widget. Since these functions depend on the state of the widget, I created a variable to store the state.
However, I am getting a compile time warning:
This class (or a class that this class inherits from) is marked as '#immutable', but one or more of its instance fields aren't final.
My Code:
class ItemWidget extends StatefulWidget {
final Record record;
final Function additem;
final Function removeItem;
var state;
ItemWidget(this.record, this.additem, this.removeItem);
#override
_ItemWidgetState createState() {
return this.state = new _ItemWidgetState();
}
// These are public functions which I need to expose.
bool isValid() => state.validate();
void validate() => state.validate();
}
Is there a better way /correct way of achieving this?
Thanks.
You should write the function on state, and access it via GlobalKey.
import 'package:flutter/material.dart';
class ItemWidget extends StatefulWidget {
final Record record;
final Function additem;
final Function removeItem;
const ItemWidget(
Key? key,
this.record,
this.additem,
this.removeItem,
) : super(key: key);
#override
ItemWidgetState createState() => ItemWidgetState();
}
class ItemWidgetState extends State<ItemWidget> {
bool isValid() {
return true;
}
void validate() {}
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
https://api.flutter.dev/flutter/widgets/GlobalKey-class.html

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.

Defining a constructor in a stateful widget in both the class and its state

I'm making a login page in a flutter app which requires a constructor that takes too parameters ( goToWelcomeListener, enterAnimation ) as shown:
abstract class GoToWelcomeListener {
void onGoToWelcomeTap();
}
class LoginScreen extends StatefulWidget {
final GoToWelcomeListener goToWelcomeListener;
final LoginEnterAnimation enterAnimation;
LoginScreen(
{#required AnimationController controller,
#required this.goToWelcomeListener})
: this.enterAnimation = new LoginEnterAnimation(controller);
State<StatefulWidget> createState() {
return new LoginScreenState();
}
}
class LoginScreenState extends State<LoginScreen> {
final GoToWelcomeListener goToWelcomeListener;
final LoginEnterAnimation enterAnimation;
final userNameController = TextEditingController();
final passwordController = TextEditingController();
final formKey = GlobalKey<FormState>();
final URL = "https://gam3ity.com/";
LoginScreenState(
{#required AnimationController controller,
#required this.goToWelcomeListener})
: this.enterAnimation = new LoginEnterAnimation(controller);
And as you can see i had to define the constructor two times for it to work and not give me errors, because if i defined it just in the state itself and not the class, it doesn't recognize it as a constructor, and if i declared it in the class without the state, i can't use any of the parameters in the state cuz it's initialized in the class not the state.
Then when i call the constructor in another file as shown:
"/LoginScreen": (BuildContext context) => LoginScreen()
Those are the warnings it gives me:
warning: The parameter 'controller' is required. (missing_required_param at
[gam3ity_aa] lib\main.dart:30)
warning: The parameter 'goToWelcomeListener' is required.
(missing_required_param at [gam3ity_aa] lib\main.dart:30)
warning: The parameter 'goToWelcomeListener' is required.
(missing_required_param at [gam3ity_aa] lib\screens\login\login_page.dart:34)
warning: The parameter 'controller' is required. (missing_required_param at
[gam3ity_aa] lib\screens\login\login_page.dart:34)
What am i missing?
Because of this! You marked that AnimationController and goToWelcomeListener are required params. But you just called LoginScreen() -> missing required params
LoginScreen(
{#required AnimationController controller,
#required this.goToWelcomeListener})
: this.enterAnimation = new LoginEnterAnimation(controller);

GlobalKey in InheritedWidget causing re-parent

Is passing a GlobalKey down the tree using an InheritedWidget an antipattern? The stateful widget using that key is re-created (i.e. a new state this initState/disposed) every time its subtree is re-built.
My InheritedWidget looks like:
import 'package:flutter/material.dart';
import '../widgets/carousel.dart';
import '../widgets/panel/panel.dart';
class _CarouselKey extends GlobalObjectKey<CarouselState> {
const _CarouselKey(Object value) : super(value);
}
class _ProgressiveChatHeaderKey extends GlobalObjectKey<PanelScaffoldState> {
const _ProgressiveChatHeaderKey(Object value) : super(value);
}
class DimensionScopedKeyProvider extends InheritedWidget {
final _CarouselKey parallelBubbleCarouselKey;
final _ProgressiveChatHeaderKey progressiveChatHeaderKey;
final String keyString;
DimensionScopedKeyProvider({
Key key,
#required this.keyString,
#required Widget child,
}) : parallelBubbleCarouselKey = _CarouselKey(keyString),
progressiveChatHeaderKey = _ProgressiveChatHeaderKey(keyString),
super(key: key, child: child);
static DimensionScopedKeyProvider of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(DimensionScopedKeyProvider)
as DimensionScopedKeyProvider);
}
#override
bool updateShouldNotify(DimensionScopedKeyProvider oldWidget) => oldWidget.keyString != keyString;
}
And this InheritedWidget is rendered with a constant keyString, meaning that 1) updateShouldNotify always returns false and 2) the hashCode of the GlobalKeys passed to my build methods via DimensionScopedKeyProvider.of() are always identical.
The stateful widget builds something like
GlobalKey<PanelScaffoldState> get _headerKey => //
DimensionScopedKeyProvider.of(context).progressiveChatHeaderKey;
// ...
PanelScaffold(
key: _headerKey,
// ...
)
When I change a property that affects the subtree that the PanelScaffold lives in, though, a new PanelScaffoldState is created and the old one is disposed, even though the widget tree hasn't changed structure and the _headerKey hasn't changed either.
I also able to solve this problem, but I have no idea why it works.
The solution is to cache the access to the GlobalKey in didChangeDependencies
#override
void didChangeDependencies() {
super.didChangeDependencies();
_headerKey ??= DimensionScopedKeyProvider.of(context).progressiveChatHeaderKey;
}
.... and now everything is working as expected again—the rebuilds re-parent the existing state.
Does anyone know why caching the getter to the GlobalKey is the key here?