Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Child Property in Stateful Widget

I’ve made some test widgets to illustrate a point that I’m having difficulty with in a much more complicated widget.

I have the following widget:

class TestListWidget extends StatefulWidget {
  Widget child;

  TestListWidget({Widget child}) {
    this.child = child;
  }

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


}
class TestListWidgetState extends State<TestListWidget>
{
  Widget child;

  int buttonCount = 0;

  @override initState() {
    child = widget.child;
  }

  _clickedCountButton()
  {
    setState(() {
      buttonCount++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Column(children: [
      Text("Times Hit: $buttonCount"),
      ElevatedButton(onPressed: _clickedCountButton, child: Text("Update Count")),
      child
    ]);
  }
}

The above widget is being used inside the following widget:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class TestList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new TestListState();
  }
}

class TestListState extends State<TestList> {
  String _testStr = "not clicked";

  _clickButton()
  {
    setState(() {
      _testStr = "CLICKED";
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "Test",
        theme: ThemeData(
        primarySwatch: Colors.blue
    ),
    home:Scaffold(
        body : testListWidget(child: Row(children: [
      Text(_testStr),
      ElevatedButton(onPressed: _clickButton, child: Text("Click me!"))
    ]))));
  }
}

The issue I’m having is when the "Click me!" button is clicked, the function is called, but the text on the screen is not updated to "CLICKED!". The "Update Count" button works as intended though.

If I make the TestListWidget a stateless widget (and remove the update count button functionality) then the "Click Me!" button works as expected. Is there any way to make a child widget rebuild when passed to a stateful widget?

>Solution :

Your problem is quite simple. You have two variables, one is TestListWidget.child, we’ll call it stateful widget’s child. The second is TestListWidgetState.child, we’ll call it state’s child.

You make state’s child to be equal to stateful widget’s child on initState, but initState only runs when you first create a state, so updating the stateful widget’s child will not update the state’s child because initState won’t run again.

To fix this, I believe you can just completely remove state’s child, and use widget.child instead:

return new Column(children: [
      Text("Times Hit: $buttonCount"),
      ElevatedButton(onPressed: _clickedCountButton, child: Text("Update Count")),
      widget.child
    ]);

Full example:

import 'package:flutter/material.dart';

void main() => runApp(TestList());

class TestListWidget extends StatefulWidget {
  Widget child;

  TestListWidget({required this.child});

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


}
class TestListWidgetState extends State<TestListWidget>
{

  int buttonCount = 0;

  _clickedCountButton()
  {
    setState(() {
      buttonCount++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Column(children: [
      Text("Times Hit: $buttonCount"),
      ElevatedButton(onPressed: _clickedCountButton, child: Text("Update Count")),
      widget.child
    ]);
  }
}

class TestList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new TestListState();
  }
}

class TestListState extends State<TestList> {
  String _testStr = "not clicked";

  _clickButton()
  {
    setState(() {
      _testStr = "CLICKED";
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "Test",
        theme: ThemeData(
        primarySwatch: Colors.blue
    ),
    home:Scaffold(
        body : TestListWidget(child: Row(children: [
      Text(_testStr),
      ElevatedButton(onPressed: _clickButton, child: Text("Click me!"))
    ]))));
  }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading