user1187968
user1187968

Reputation: 8026

Flutter setState on sibling widgets

In the following, my Sort mixin class created a list of ItemStatefulWidget widgets,

When a user clicks on a ItemStatefulWidget widget, it calls setState() to update the values stored in globalSortConfig, which is used by other sibling widgets.

However, setState didn't trigger rebuild in other sibling widgets.

Sort Mixin Source Code:

import 'package:flutter/material.dart';

dynamic globalSortConfig = null;

//
// Sort Mixin
//
mixin Sort<T extends StatefulWidget> on State<T> {
  List<Widget> sortWidgets;
  dynamic mixinSorts;

  @override
  void initState() {
    super.initState();
  }

  void showSortModal(context, Function callback) {
    // set global sort config
    if(globalSortConfig == null) {
      globalSortConfig = mixinSorts;
    }

    // show modal
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        // build sort widgets 
        if (sortWidgets == null) {
          sortWidgets = [];
          for (var i = 0; i < mixinSorts.length; i++) {
            sortWidgets.add(ItemStatefulWidget(i: i, callback: callback));
          }
        }
        
        // return 
        return Container(
          child: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: sortWidgets),
          ),
        );
      },
    );
  }
  
  dynamic getSortCriteria() {
    dynamic criteria = {};
    if (globalSortConfig != null) {
      for (var i = 0; i < globalSortConfig.length; i++) {
        if (globalSortConfig[i]['select'] == true) {
          criteria['sort'] = globalSortConfig[i]['sort'];
          criteria['order'] = globalSortConfig[i]['order'];
        }
      }
    }
    return criteria;
  }
}

ItemStatefulWidget Source code

class ItemStatefulWidget extends StatefulWidget {
  final int i;
  final Function callback;

  ItemStatefulWidget({Key key, this.i, this.callback}) : super(key: key);

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

class _ItemStatefulWidgetState extends State<ItemStatefulWidget> {

  @override
  Widget build(BuildContext context) {
    // var
    int i = this.widget.i;
    List<Widget> lineWidgets = [];

    // checked icon
    if (globalSortConfig[i]['select'] == true) {
      Widget iconWidget = Icon(Icons.check);
      lineWidgets.add(iconWidget);
    }

    // label
    String label =  globalSortConfig[i]['label'];

    lineWidgets.add(GestureDetector(
      child: Text(label,
        style: TextStyle(fontSize: 20),
      ),
      onTap: () {
        setState(() {

          // update value
          globalSortConfig[i]['select'] = !globalSortConfig[i]['select'];
          for (var w = 0; w < globalSortConfig.length; w++) {
            if (w != i) {
              globalSortConfig[w]['select'] = false;
            }
          }

          // pop and callback
          Future.delayed(const Duration(microseconds: 900), () {
            Navigator.pop(context);
            this.widget.callback();
          });
        });
      },
    ));

    // alignment
    Widget row = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: lineWidgets,
    );
    return row;
  }
}

Upvotes: 1

Views: 279

Answers (1)

Bram
Bram

Reputation: 680

It's not clear from you code what exactly the callback function is or does, but it is only ever called on this.widget, not on others. If you want the tap of one widget to trigger changes in the others, then I think a much cleaner way to implement this is to make your globalSortConfig a (singleton?) object of a class that extends ChangeNotifierProvider from the Provider package. To change your config in the onTap of the ItemStatefulWidget you can then call a method on that object that also calls notifyListeners(), and in the build method of the ItemStatefulWidget you listen to those changes using context.watch, which will ensure that each ItemStatefulWidget is rebuilt whenever the globalSortConfig object changes.

Upvotes: 1

Related Questions