Why setState in parent StatefulWidget do not update child StatefulWidget

946 views Asked by At

I know, that correct way to update child StatefulWidget from parent StatefulWidget is to use child GlobalKey instance.

But i cant understand, why setState(() {}) not doing the same! I didnt found any documentation or explanation about this.

From documentation:

Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this State object.

If you just change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.

By documenation, i expect that whole widgets subtree will be updated. But it dont.

Pls, explain me, why example below do not work as expected (change text of ChildStatefulWidget). Thanks!

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

class ParentStatefulWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ParentState();
  }
}

class ParentState extends State<ParentStatefulWidget> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        GestureDetector(
          child: Container(
              color: Colors.lightBlue,
              padding: EdgeInsets.all(10),
              child: Text(
                "Tap me",
                style: TextStyle(color: Colors.white, fontSize: 24),
              )),
          onTap: () {
            setState(() {
              counter = counter + 1;
            });
          },
        ),
        ChildStatefulWidget(
          text: "Count: $counter",
        )
      ],
    );
  }
}

class ChildStatefulWidget extends StatefulWidget {
  final String text;

  ChildStatefulWidget({Key key, this.text = ""}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return ChildState(text);
  }
}

class ChildState extends State<ChildStatefulWidget> {
  final String text;

  ChildState(this.text);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(fontSize: 18),
    );
  }
}
1

There are 1 answers

0
Alexander Seednov On BEST ANSWER

You don't need to create "text" in childState - just take "widget.text":

class ChildState extends State<ChildStatefulWidget> {    
  @override
  Widget build(BuildContext context) {
    return Text(
      widget.text,
      style: TextStyle(fontSize: 18),
    );
  }
}

Your code doesn't work because you sending value throw constructor but constructor doesn't call every time when you changing state. So the getted throw constructor value doesn't changing.