10

I'm kinda confused, I have been looking into state management with flutter recently and I was wondering what happens if a custom stateful widget is placed in a stateless widget, let's say widgetA (parent) is a stateless widget and it has a child WidgetB which is a stateful widget and another child WidgetC which is a stateless widget.

Now my questions are:

  • if setState() is called from widgetB, are WidgetA, B, and C rebuilt?
  • how does this compare to using different state Management techniques like State provider, stream builders, or Bloc?
  • when to use setState()?
  • is it smart to combine multiple State management techniques?

if you have external links or resources that can help me understand please provide them

Nayef Radwi
  • 1,305
  • 13
  • 25

2 Answers2

9

If I say something wrong, someone please correct me.

Answering your questions in order:

  1. If you call setState() on WidgetB it'll rebuild itself and it's descendants, no matter if they are Stateless or Stateful Widgets.

  2. Using the BLoC approach, most of the times it's optional to use Stateful Widgets and setState() to manage State. In this approach you'll use events from the UI, which will be converted into 'States' inside your BLoC. This States will be passed into a Stream. Your UI will rebuild itself using StreamBuilders every time they listen to a new value on the Stream they're listening. This will trigger the StreamBuilder to rebuilt itself and it's descendants.

  3. If you're using BLoC or Provider + Streams, I would recommend avoiding setState() and StatefulWidgets, maybe with some exceptions like UI things, eg. animations.

  4. BLoC is a design approach with goes nice with the Provider package. The BLoC package even uses Provider internally.

P.S.: Whereas BLoC is an Architecture Pattern to manage the Data and State of your application. Provider is 'just' a wrapper around Inherited Widgets that facilitate exposure of Data throughout your Widget tree, not an Architecture Pattern.

Other example of architecture pattern solution to manage state that uses the provider package is MobX.

pedro pimont
  • 2,764
  • 1
  • 11
  • 24
  • 1
    In number 4, "The BLoC package even uses Provider internally.", this might cause people to think that the bloc package uses provider to handle the state; While it's not that way and It uses provider only to provide a bloc to the widget tree. – Ali Alizadeh Jul 10 '20 at 20:22
  • @AliAlizadeh just added this comment to make it clearer – pedro pimont Jul 10 '20 at 20:48
  • In number 1, descendants or children with `const` prefix will not rebuild if`setState` is called on the parent. However, if you remove the `const` prefix it will rebuild that child widget. – nivla360 Aug 28 '22 at 09:12
3

setState() will call the build() method and rebuilds with widget tree (With Flutter optimizations under the hood), if you wish to build only a part there is an Alternative: create a Provider that holds the change that you want to reflect in the UI, and wrap that widget with a Consumer - when you will call notifyListener() from the Provider only that Widget will rebuild.

For Example:

 child: Consumer<MessageIconStateProvider>(
        builder: (context, messageIconProvider, child) {
          return Container(
            height: 40,
            child: messageIconProvider.isShowMessageIcon
                ? Icon(
              Icons.send,
              size: 24,
              color: Colors.white,
            )
                : Icon(
              Icons.mic_outlined,
              size: 24,
              color: Colors.white,
            ),
          );
        }
    )

The provider:

 import 'package:flutter/material.dart';

class MessageIconStateProvider with ChangeNotifier {
  var isShowMessageIcon = true;
  
  void setIconToMessage(bool setIconToMessage){
    if(setIconToMessage != isShowMessageIcon) {
      isShowMessageIcon = setIconToMessage;
      notifyListeners();
    }
  }


}

And don't forget to define it on your main.dart file:

    class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => MessageIconStateProvider()),
      ],...
Gal Rom
  • 6,221
  • 3
  • 41
  • 33
  • When you say “only that Widget will rebuild” does it mean _only_ that widget (and not any descendant Widgets) or “only the Widget tree from that node down”? – sleighty Oct 08 '21 at 10:01