Haris
Haris

Reputation: 129

Flutter TabBarView and BottomNavigationBar pages are not refreshing with SetState

I have the following Flutter BottomNavigationBar, I have 3 children page widgets. As soon as the user writes a review and press the submit button, I am calling the void _clear() which resets the values in the textfield widgets. This method is inside and called from the WriteReview widget but is not working, the screen is not refreshing. The data it self is being reset but the UI has not be refreshed. I tried with and without setState(){ _clear()}; but no results.

I have similar issue with the TabBarView. What I would expect as a result would be the selected widget page to be refreshed.

I assume is something different on how the widgets are being handled in the TabBarView and BottomNavigationBar that I am missing.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class HomeView extends StatefulWidget {
  @override
  _HomeViewState createState() => _HomeViewState();
}

class _HomeViewState extends State<HomeView> {
  final String _writeReviewLabel = 'Write review';
  final String _searchLabel = 'Search';
  final String _accountLabel = 'Account';

  var _currentIndex = 0;

  final List<Widget> _bottomBarItems = [
    WriteReviewView(),
    SearchView(),
    UserAccountView()
  ];

  @override
  Widget build(BuildContext context) {
    final accentColor = Theme.of(context).accentColor;
    final primaryColor = Theme.of(context).primaryColor;
    return BaseView<HomePresenter>(
      createPresenter: () => HomePresenter(),
      onInitialize: (presenter) {
        _currentIndex = ModalRoute.of(context).settings.arguments;
      },
      builder: (context, child, presenter) => Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            backgroundColor: primaryColor,
            selectedItemColor: accentColor,
            unselectedItemColor: Colors.white,
            elevation: 0,
            currentIndex: _currentIndex,
            onTap: (index) {
              onTabTapped(index, presenter);
            },
            items: [
              BottomNavigationBarItem(
                activeIcon: Icon(Icons.rate_review),
                icon: Icon(Icons.rate_review),
                title: Text(_writeReviewLabel),
              ),
              BottomNavigationBarItem(
                activeIcon: Icon(Icons.search),
                icon: Icon(Icons.search),
                title: Text(_searchLabel),
              ),
              BottomNavigationBarItem(
                  activeIcon: Icon(Icons.person),
                  icon: Icon(Icons.person),
                  title: Text(_accountLabel)),
            ],
          ),
          body: _bottomBarItems[_currentIndex]),
    );
  }

  void onTabTapped(int index, HomePresenter presenter) {
    if (index == _currentIndex) {
      return;
    }

    if (presenter.isAuthenticated) {
      setState(() {
        _currentIndex = index;
      });
    } else {
      presenter.pushNamed(context, Routes.login, arguments: () {
        if (presenter.isAuthenticated) {
          Future.delayed(const Duration(microseconds: 500), () {
            setState(() {
              _currentIndex = index;
            });
          });
        }
      });
    }
  }
}

Write Review View

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'base/BaseView.dart';

class WriteReviewView extends StatefulWidget {
  @override
  _WriteReviewViewState createState() => _WriteReviewViewState();
}

class _WriteReviewViewState extends State<WriteReviewView> {
  final String _locationLabel = 'Location';
  final String _reviewLabel = 'Review';

  @override
  Widget build(BuildContext context) {
    return BaseView<WriteReviewPresenter>(
        createPresenter: () => WriteReviewPresenter(),
        onInitialize: (presenter) {
          presenter.init();
        },
        builder: (context, child, presenter) => Container(
              color: Theme.of(context).backgroundColor,
              child: _body(presenter),
            ));
  }

  Widget _body(WriteReviewPresenter presenter) {
    final height = MediaQuery.of(context).size.height;
    return LayoutBuilder(builder: (context, constraint) {
      return SingleChildScrollView(
        child: ConstrainedBox(
          constraints: BoxConstraints(minHeight: constraint.maxHeight),
          child: IntrinsicHeight(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Card(
                  margin: EdgeInsets.fromLTRB(4.0, 4.0, 4.0, 8.0),
                  child: Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 8.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: <Widget>[
                        Padding(
                          padding: EdgeInsets.only(top: 10, bottom: 20),
                          child: Row(
                            children: [
                              Icon(Icons.location_on,
                                  color: Theme.of(context).cursorColor),
                              SectionTitle(_locationLabel),
                            ],
                          ),
                        ),
                        ChooseAddressButton(presenter.addressContainer.address, () {
                          presenter.navigateNewAddress(context);
                        }),
                        SizedBoxes.medium,
                      ],
                    ),
                  ),
                ),
                Card(
                  margin: EdgeInsets.fromLTRB(4.0, 4.0, 4.0, 8.0),
                  child: Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 8.0),
                    child: Column(
                      children: [
                        Padding(
                          padding: EdgeInsets.only(top: 10),
                          child: Row(
                            children: [
                              Icon(Icons.star, color: Theme.of(context).indicatorColor),
                              SectionTitle(_reviewLabel),
                            ],
                          ),
                        ),
                        SizedBoxes.medium,
                        CustomTextFormField(
                            data: presenter.reviewContainer.review,
                            showMinimum: true,
                            characterLimit: 50,
                            maxLines: 4,
                            height: 100),
                        ModifyRatingBar(50.0, presenter.reviewContainer.rating, false),
                        Padding(
                            padding: EdgeInsets.symmetric(vertical: 5),
                            child: Divider(indent: 40, endIndent: 40)),
                      ],
                    ),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 10),
                  child: Card(
                    color: Theme.of(context).accentColor,
                    child: FlatButton(
                      onPressed: () {
                        _submit(context, presenter);
                      },
                      child: Text('Submit',style:TextStyle(fontWeight: FontWeight.bold,fontSize: 18,color: Colors.white)),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    });
  }

  void _submit(BuildContext context, WriteReviewPresenter presenter) async {
    LoadingPopup.show(context);

    final status = await presenter.submit(context);

    LoadingPopup.hide(context);

    if (status == ReviewStatus.successful) {
      PostCompletePopup.show(context);
      setState(() {
        presenter.clear();
      });
    } else {
      presenter.showError(context, status);
    }
  }
}

Upvotes: 1

Views: 1111

Answers (1)

Bar Tzadok
Bar Tzadok

Reputation: 516

setState() only refreshes the widget that called it, and all the widgets under it.

When calling setState()from WriteReview widget, it will not update the HomeView widget. Try moving the setState()call to the HomeView widget using some sort of callback.

Upvotes: 1

Related Questions