getter causes maximum call stack size exceeded flutter - flutter

I have the following widget:
class VennDiagramWidget extends StatefulWidget {
VennDiagramWidget(selectedGeneLists);
List<GenesListObjIndexed> get selectedGeneLists => this.selectedGeneLists;
#override
_VennState createState() => _VennState();
}
class _VennState extends State<VennDiagramWidget> {
List<GenesListObjIndexed> _selectedGeneLists;
#override
initState() {
_selectedGeneLists = widget.selectedGeneLists;
}
This widget is intialized by another widget in this way:
.
.
.
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => VennDiagramWidget(selectedGeneLists)));
I get and error of Maximum call stack size exceeded on this line:
_selectedGeneLists = widget.selectedGeneLists; inside initState.
To my knowledge, this code is supposed to construct the class VennDiagramWidget with the selectedGeneLists I have specified on the second snippet, and when I am calling the getter of this class, I should get the exact same variable.
What am I doing wrong?

the problem is, when you're calling the getter selectedGeneLists it's calling itself again
// calling itself ⬇
get selectedGeneLists => this.selectedGeneLists;
you need to declare selectedGeneLists variable in the widget class
this should work
class VennDiagramWidget extends StatefulWidget {
final selectedGeneLists;
VennDiagramWidget(this.selectedGeneLists);
#override
_VennState createState() => _VennState();
}
or this if you want the variable private
class VennDiagramWidget extends StatefulWidget {
final _selectedGeneLists;
VennDiagramWidget(this._selectedGeneLists);
List<GenesListObjIndexed> get selectedGeneLists => this._selectedGeneLists;
#override
_VennState createState() => _VennState();
}

Related

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

TypeError when calling a generic callback [duplicate]

I have a generic StatefulWidget class that has a Function callback. When I try to invoke that callback, I get a runtime TypeError:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following _TypeError was thrown building MyStatefulWidget<int>(dirty, state:
MyState<int>#cacb3):
type '(int) => Widget' is not a subtype of type '(dynamic) => Widget'
The relevant error-causing widget was:
MyStatefulWidget<int>
MyStatefulWidget:file:///path/to/my_flutter_project/lib/main.dart:11:13
When the exception was thrown, this was the stack:
#0 MyState.build (package:my_flutter_project/main.dart:33:19)
Reproducible example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Widget f(int n) => Text('$n');
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyStatefulWidget<int>(callback: foo, value: 42),
);
}
}
class MyStatefulWidget<T> extends StatefulWidget {
final Widget Function(T) callback;
final T value;
const MyStatefulWidget({
required this.callback,
required this.value,
Key? key,
}) : super(key: key);
#override
MyState<T> createState() => MyState<T>();
}
class MyState<T> extends State<MyStatefulWidget> {
#override
Widget build(BuildContext context) {
return widget.callback(widget.value);
}
}
I've tried explicitly constructing MyStatefulWidget as MyStatefulWidget<int>, but that doesn't help. Where is the Widget Function(dynamic) type coming from?
MyState createState() => MyState(); omits the type arguments, so it returns a MyState, which is shorthand for MyState<dynamic>.
Additionally, MyState<T> extends State<MyStatefulWidget> is shorthand for ... extends State<MyStatefulWidget<dynamic>>, not for ... extends State<MyStatefulWidget<T>> as intended.
The static type of the MyState<T>'s inherited widget member therefore will be MyStatefulWidget<dynamic>, and the static type of widget.callback will be Widget Function(dynamic). At runtime, the associated MyStatefulWidget object has a reference to f (a Widget Function(int). However, that cannot be treated as Widget Function(dynamic) (as expected by MyState<T>) since f cannot accept all dynamic arguments, so you end up with a TypeError at runtime.
Bottom line
If you have a generic StatefulWidget, you must explicitly and consistently supply the type parameters everywhere that the StatefulWidget refers to its State class or where the State refers to its StatefulWidget class. Common mistakes are:
Neglecting type parameters in createState.
Neglecting type parameters when declaring inheritance for the corresponding State class.
So:
class MyStatefulWidget<T> extends StatefulWidget {
...
MyState createState() => MyState(); // WRONG
}
class MyState<T> extends State<MyStatefulWidget> { // WRONG
...
}
instead should be:
class MyStatefulWidget<T> extends StatefulWidget {
...
MyState<T> createState() => MyState<T>();
}
class MyState<T> extends State<MyStatefulWidget<T>>
...
}
The strict_raw_types analysis option sometimes can help catch such mistakes, although the current implementation seems to check only for implicitly dynamic type parameters and doesn't seem to catch cases where the type parameter is restricted (such as if you have MyStatefulWidget<T extends num>).

The instance 'widget' can't be accessed in an initializer

I'm having trouble accessing the variable user on _MenuScreenState:
class MenuScreen extends StatefulWidget {
final User user;
MenuScreen(this.user);
#override
_MenuScreenState createState() => _MenuScreenState();
}
class _MenuScreenState extends State<MenuScreen> {
final User userInMenu = widget.user;
}
The problem displayed is "The instance member 'widget' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression".
You have to do it inside initState like the following:
class MenuScreen extends StatefulWidget {
final User user;
MenuScreen(this.user);
#override
_MenuScreenState createState() => _MenuScreenState();
}
class _MenuScreenState extends State<MenuScreen> {
User userInMenu = widget.user;
#override
void initState() {
super.initState();
userInMenu = widget.user;
}

The instance member 'widget' can't be accessed in an initializer

In my project, I pass data from one widget to another using this code:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
TranslatorSignUpStep2(transModel: this._translatorModel),
),
);
Then I retrive it in the other widget by the code below:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
The problem is, in the TranslatorSignUpStep2 class I want to assign the passed-in transModel to another variable so I write this code
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel = widget.transModel;
}
But it seems like the widget can't be used outside the build method so I get error saying
The instance member 'widget' can't be accessed in an initializer.. Anyone know how to get over this ?
you can access widget in initState function like this.
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel ;
#override
void initState() {
_translatorModel = widget.transModel;
}
}
Just add the keyword late while initializing:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
late TranslatorModel _translatorModel = widget.transModel;
}
try this code :
TranslatorSignUpStep2 :
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State(this.transModel);
}
TranslatorSignUpStep2 class :
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
_TranslatorSignUpStep2State(TranslatorModel _tempModel ){
this._translatorModel =_tempModel;
};
TranslatorModel _translatorModel ;
}
Add static keyword when innitializing
class OrderDetails extends StatefulWidget {
int selectedDays;
OrderDetails({
this.range,)};
#override
_OrderDetailsState createState() => _OrderDetailsState();
}
class _OrderDetailsState extends State<OrderDetails> {
String getRange;
#override
void initState() {
super.initState();
getRange = widget.range;
}

How to call a function in a StatefulWidget from another StatefulWidget?

I am trying to call a function(addGeoPoint) from Map class in another function named onDragEnd of the class SwipeButton both of which is are stateful.
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
}
File 2
class SwipeButton extends StatefulWidget {
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
}
}
To do so, I tried creating an instance of the class Map as Map mapScreen = new Map and then access the function using mapScreen.addGeoPoint() but, I achieved no success. Any help to solve this problem would be appreciated.
You can use VoidCallBacks to communicate between Widgets:
Map:
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
//do things
}
Widget buildSwipeButton() {
...
...
return SwipeButton(
onAddGeoPoint: addGeoPoint,
);
}
SwipeButton:
class SwipeButton extends StatefulWidget {
final VoidCallback onAddGeopoint;
SwipeButton({this.onAddGeoPoint});
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
widget.onAddGeoPoint();
}
}
You can declare your widget like this
class YourWidget extends StatefulWidget {
final Function callback;
YourWidget({#required this.textButton});
#override
YourWidgetState createState() => YourWidgetState();
}
then you can pass de function like this in your stateful parent
YourWidget(
callback: (){}
)
ant then you can use in YourWidget like this in other widget or other function
widget.callback()