256

I have 2 screens in my Flutter app: a list of records and a screen for creating and editing records.

If I pass an object to the second screen that means I am going to edit this and if I pass null it means that I am creating a new item. The editing screen is a Stateful widget and I am not sure how to use this approach https://flutter.io/cookbook/navigation/passing-data/ for my case.

class RecordPage extends StatefulWidget {
  final Record recordObject;

  RecordPage({Key key, @required this.recordObject}) : super(key: key);

  @override
  _RecordPageState createState() => new _RecordPageState();
}

class _RecordPageState extends State<RecordPage> {
  @override
  Widget build(BuildContext context) {
   //.....
  }
}

How can I access recordObject inside _RecordPageState?

Paresh Mangukiya
  • 37,512
  • 17
  • 201
  • 182
moonvader
  • 16,681
  • 16
  • 62
  • 106
  • 3
    Possible duplicate of [Passing Data to a Stateful Widget](https://stackoverflow.com/questions/50818770/passing-data-to-a-stateful-widget) – Herohtar Feb 04 '19 at 19:42
  • how can we use 'recordObject' variable value in a function of _RecordPageState class? – Kamlesh Mar 08 '20 at 07:56
  • 2
    Does this answer your question? [Pass StatefulWidget data to the State class without using constructor](https://stackoverflow.com/questions/50428708/pass-statefulwidget-data-to-the-state-class-without-using-constructor) – Blasanka Mar 11 '20 at 10:35

6 Answers6

398

To use recordObject in _RecordPageState, you have to just write widget.objectname like below

class _RecordPageState extends State<RecordPage> {
  @override
  Widget build(BuildContext context) {
   .....
   widget.recordObject
   .....
  }
}
Dhrumil Shah - dhuma1981
  • 13,136
  • 6
  • 29
  • 38
  • 12
    Those who are new to Flutter, do not forget to define widget like '@override RecordPage get widget => super.widget;' – hhk Oct 14 '18 at 17:09
  • 30
    @hhk Why is that necessary? – Herohtar Feb 04 '19 at 19:39
  • 5
    Should't the `recordObject` be part of the `State` class? Logically, having it in `StatefulWidget` is incorrect (in terms of cohesion). Besides, all fields of `StatefulWidget` should be immutable - what if you want to change the `recordObject` reference? – Alex Semeniuk Jul 25 '19 at 09:43
  • I have exactly the same and it's not working doing something like `Text(widget.recordObject)`, it says that my var is null – Dani Oct 23 '19 at 21:32
  • 1
    how can we use 'recordObject' variable value in a function of _RecordPageState class? – Kamlesh Mar 08 '20 at 07:56
  • 2
    It does not seem necessary to define the widget as in @hhk's comment anymore. – Filippos Zofakis Oct 11 '20 at 12:50
  • 1
    What if I want to change the field in RecordPage at runtime? Is pass the field to State class as an constructor argument is a better way? – NM Naufaldo May 26 '21 at 06:05
73

Full Example

You don't need to pass parameters to State using it's constructor. You can easily access these using widget.myField.

class MyRecord extends StatefulWidget {
  final String recordName;
  const MyRecord(this.recordName);

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

class MyRecordState extends State<MyRecord> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.recordName); // Here you direct access using widget
  }
}

Pass your data when you Navigate screen :

 Navigator.of(context).push(MaterialPageRoute(builder: (context) => MyRecord("WonderWorld")));
Sanjayrajsinh
  • 11,663
  • 3
  • 65
  • 73
46
class RecordPage extends StatefulWidget {
  final Record recordObject;

  RecordPage({Key key, @required this.recordObject}) : super(key: key);

  @override
  _RecordPageState createState() => new _RecordPageState(recordObject);
}

class _RecordPageState extends State<RecordPage> {
  Record  recordObject
 _RecordPageState(this. recordObject);  //constructor
  @override
  Widget build(BuildContext context) {.    //closure has access
   //.....
  }
}
John Mcfetridge
  • 1,087
  • 1
  • 10
  • 13
  • 1
    Please explain why this is a statefull widget. – atilkan Jun 06 '19 at 14:27
  • 1
    @atilkan because OP initial script is a StatefulWidget, he just added some lines to fit the needs. – adadion Jun 28 '19 at 04:44
  • 4
    I do not think that having `recordObject` field both in `State` and `StatefulWidget` classes is such a good idea (even though I saw tutorials doing exactly this). The approach of accessing fields of `StatefulWidget` by using `widget` field of `State` class seem like a more correct approach (even though it has its own problems) – Alex Semeniuk Jul 25 '19 at 09:41
6

example as below:

class nhaphangle extends StatefulWidget {
  final String username;
  final List<String> dshangle;// = ["1","2"];
  const nhaphangle({ Key key, @required this.username,@required this.dshangle }) : super(key: key);


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

class _nhaphangleState extends State<nhaphangle> {
  TextEditingController mspController = TextEditingController();
  TextEditingController soluongController = TextEditingController();
  final scrollDirection = Axis.vertical;
  DateTime Ngaysx  = DateTime.now();
  ScrollController _scrollController = new ScrollController();

  ApiService _apiService;
  List<String> titles = [];

  @override
  void initState() {
    super.initState();
    _apiService = ApiService();
    titles = widget.dshangle;  //here var is call and set to 
  }

    
3

I have to Navigate back to any one of the screens in the list pages but when I did that my onTap function stops working and navigation stops.

class MyBar extends StatefulWidget {
  MyBar({this.pageNumber});
  final pageNumber;
  static const String id = 'mybar_screen';
  @override
  _MyBarState createState() => _MyBarState();
}

class _MyBarState extends State<MyBar> {
  final List pages = [
    NotificationScreen(),
    AppointmentScreen(),
    RequestBloodScreen(),
    ProfileScreen(),
  ];
  @override
  Widget build(BuildContext context) {
    var _selectedItemIndex = widget.pageNumber;
    return Scaffold(
        bottomNavigationBar: BottomNavigationBar(
          elevation: 0,
          backgroundColor: Colors.white,
          unselectedItemColor: Colors.grey.shade700,
          selectedItemColor: Color(kAppColor),
          selectedIconTheme: IconThemeData(color: Color(kAppColor)),
          currentIndex: _selectedItemIndex,
          type: BottomNavigationBarType.fixed,
          onTap: (int index) {
            setState(() {
              _selectedItemIndex = index;
            });
          },
Bilal Ali
  • 31
  • 4
-1

In my app, often instead of using stateful widgets, I use mainly ChangeNotifierProvider<T> in main.dart, some model class

class FooModel extends ChangeNotifier {

var _foo = false;

void changeFooState() {
   _foo = true;
   notifyListeners();
}

bool getFoo () => _foo;

}

and

var foo = context.read<FooModel>();
# or
var foo = context.watch<FooModel>();

in my stateless widgets. IMO this gives me more precise control over the rebuilding upon runtime state change, compared to stateful widgets.

The recipe can be found in the official docs, the concept is called "lifting state up".

G. Debailly
  • 773
  • 1
  • 7
  • 11