Pass parameter to initState

5,402

Pass such parameter to the StatefulWidget subclass, and use that field instead

class Foo extends StatefulWidget {
  const Foo({Key key, this.isMyEvent}) : super(key: key);

  final bool isMyEvent;

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

class _FooState extends State<Foo> {
  @override
  void initState() {
    super.initState();
    print(widget.isMyEvent);
  }

  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }
}
Share:
5,402
user1209216
Author by

user1209216

Updated on December 09, 2022

Comments

  • user1209216
    user1209216 over 1 year

    Look at this code - widget to fetch data and display on list:

    class _MyEventsFragmentState extends State <MyEventsFragment>{
    
      var events;
    
      @override
      initState(){
        super.initState();
        events = fetchEvents(true);
      }
    
      @override
      Widget build(BuildContext context) {
        return new Center(
            child: FutureBuilder<EventsResponse>(
              future: events,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasError) {
                    helpers.logout(context, Strings.msg_session_expired);
                    return CircularProgressIndicator();
                  }
                  return new Container(color: Colors.white,
                      child: new ListControl().build(snapshot));
                }
                return CircularProgressIndicator();
              },
            )
        );
      }
    }
    

    fetchEvent method has parameter to indicate which events I need to fetch. If set to true, - my events, if set to false - all events returned. Above code loads my events and fetchEvents is called inside initState override to avoid unnecesary data reloading.

    To fetch all events I defined another class:

    class EventsFragment extends StatefulWidget {
    
      @override
      _EventsFragmentState createState() => new _EventsFragmentState();
    }
    
    class _EventsFragmentState extends State <EventsFragment>{
    
      var events;
    
      @override
      initState(){
        super.initState();
        events = fetchEvents(false);
      }
    
      @override
      Widget build(BuildContext context) {
        return new Center(
            child: FutureBuilder<EventsResponse>(
              future: events,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasError) {
                    helpers.logout(context, Strings.msg_session_expired);
                    return CircularProgressIndicator();
                  }
                  return new Container(color: Colors.white,
                      child: new ListControl().build(snapshot));
                }
                return CircularProgressIndicator();
              },
            )
        );
      }
    }
    

    But this is very dumb solution, because code is almost the same. So I tried to pass boolean value to indicate which events to load, something like that:

    @override
      initState(){
        super.initState();
        events = fetchEvents(isMyEvents);
      }
    

    isMyEvents should be got from EventsFragment constructor. However, it won't be accesible inside initState. Ho to pass it properly? I could access it inside build override, but not inside initState. How to pass it properly and make sure it will be refreshed every time widget instance is created?

    [edit]

    So this how I solved my problem (it seems to be fine):

    class EventsFragment extends StatefulWidget {
      const EventsFragment({Key key, this.isMyEvent}) : super(key: key);
    
      final bool isMyEvent;
    
      @override
      _EventsFragmentState createState() => new _EventsFragmentState();
    }
    
    class _EventsFragmentState extends State <EventsFragment>{
    
      var events;
    
      @override
      initState(){
        super.initState();
        events = fetchEvents(widget.isMyEvent);
      }
    
      @override
      void didUpdateWidget(EventsFragment oldWidget) {
    
        if(oldWidget.isMyEvent != widget.isMyEvent)
          events = fetchEvents(widget.isMyEvent);
    
        super.didUpdateWidget(oldWidget);
      }
    
      @override
      Widget build(BuildContext context) {
        return new Center(
            child: FutureBuilder<EventsResponse>(
              future: events,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasError) {
                    helpers.logout(context, Strings.msg_session_expired);
                    return CircularProgressIndicator();
                  }
                  return new Container(color: Colors.white,
                      child: new ListControl().build(snapshot));
                }
                return CircularProgressIndicator();
              },
            )
        );
      }
    }