0

I have a function called pickDateRange and, for some reason, dateRangePicker does not update its value in widget after setState. I would like to know how to solve it. When I print the value of dateRangePicker from function body it changes, but in the widget nothing happend.

class _DealsInfoSectionState extends State<DealsInfoSection> {
  DateTimeRange dateTimeRange =
      DateTimeRange(start: DateTime.now(), end: DateTime.now());
  bool doItOnce = false;

  @override
  void initState() {
    super.initState();
    context.read<DealsBloc>().add(const FetchDeals());
  }

Future _pickDateRange(DateTimeRange dateTimeRange) async {
    DateTimeRange? newDateRange = await showDateRangePicker(
        context: context,
        initialDateRange: dateTimeRange,
        firstDate: DateTime(2010),
        lastDate: DateTime(2030),
        builder: (BuildContext? context, Widget? child) {
          return StatefulBuilder( ///<<here
              builder: (context, stateSetter) { ///<<here
                return FittedBox(
                  child: Theme(
                    data: ThemeData(
                      primaryColor: colorBlue,
                    ),
                    child: child!,
                  ),
                );
              }
          );
        });

    if (newDateRange == null) return;

    setState(() {
      dateTimeRange = newDateRange;
    });
    print(dateTimeRange);
    context.read<DealsBloc>().add(FetchDealsWithDate(
        startDate: newDateRange.start.millisecondsSinceEpoch,
        endDate: newDateRange.end.millisecondsSinceEpoch + 86400000));
  }

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    var income = 0.0;

    return Container(
  width: width * 0.85,
  child: BlocBuilder<DealsBloc, DealsState>(
      builder: (context, state) {
        income = 0;
        if (state.deals.isNotEmpty) {
          state.deals.forEach((element) {
            income += element.amount;
          });
          if (!doItOnce) {
            dateTimeRange = DateTimeRange(
                start: DateTime.fromMillisecondsSinceEpoch(
                    state.deals[state.deals.length - 1].dateCreated),
                end: DateTime.fromMillisecondsSinceEpoch(
                    state.deals[0].dateCreated));
            doItOnce = !doItOnce;
            print(dateTimeRange);
          }
        }
        return Column(children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                'Date: ',
                style: Theme
                    .of(context)
                    .textTheme
                    .headline6,
              ),
              InkWell(
                onTap: () => _pickDateRange(dateTimeRange),
                child: Text(
                  '${DateFormat('yyyy/MM/dd').format(
                      dateTimeRange.start)} - '
                      '${DateFormat('yyyy/MM/dd').format(
                      dateTimeRange.end)}',
                  style: Theme
                      .of(context)
                      .textTheme
                      .subtitle1
                      ?.copyWith(color: Colors.black),
                ),
              )
            ],
          )
        ]);
       }
     ),
   );
  }
}

Output:

I/flutter (25750): 2023-01-01 00:00:00.000 - 2023-01-05 10:51:12.127

When I choose a range

I/flutter (25750): 2023-01-02 00:00:00.000 - 2023-01-04 00:00:00.000

Output is right, but nothing is updated in Widget

Timson01
  • 35
  • 5

2 Answers2

1

You are not able to see changes because Widgets are in the scope of BlocBuilder

Mistake:

Builder
|_       you are setting state here
|_ BlocBuilder
   |_ Widget     Your widget which is listening

Correct Way:

Builder
|_               setState here
|_Widget         Observable widget should be here
|_ BlocBuilder
  |_ 
krishnaacharyaa
  • 14,953
  • 4
  • 49
  • 88
1

I think this is how it should be

...

  InkWell(
                onTap: ()async{
 DateTimeRange? newDateRange = await showDateRangePicker(
                                  context: context,
                                  initialDateRange: dateTimeRange,
                                  firstDate: DateTime(2010),
                                  lastDate: DateTime(2030),
                                  builder: (BuildContext? context, Widget? child) {
                                    return FittedBox(
                                      child: Theme(
                                        data: ThemeData(
                                          primaryColor: colorBlue,
                                        ),
                                        child: child!,
                                      ),
                                    );

                                  });

                              if(newDateRange != null){
                                setState(() {
                                  dateTimeRange = newDateRange;
                                });
                              };
        context.read<DealsBloc>().add(FetchDealsWithDate(
          startDate: newDateRange.start.millisecondsSinceEpoch,
          endDate: newDateRange.end.millisecondsSinceEpoch + 
        86400000));
 }                
Davis
  • 1,219
  • 2
  • 8
  • 17
  • Thank you for your answer, but i can't use stateSetter(()){} outside of StatefulBuilder – Timson01 Jan 05 '23 at 11:30
  • I did like you said, but it does not work because i can't get "newDateRange" in StatefulBuilder – Timson01 Jan 05 '23 at 11:41
  • I've also noted that you are calling _pickDateRange and setting outside the scope let me rewrite the code. – Davis Jan 05 '23 at 12:01