How to change a State of a StatefulWidget inside a StatelessWidget?

7,207

Solution 1

I have approached this problem by initializing the _TestTextState as the final property of the TestText widget which allows to simply update the state when the change button is pressed. It seems like a simple solution but I'm not sure whether it's a good practice.

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Test app',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text("Test"),
        ),
        body: new Test(),
      ),
    );
  }
}

class Test extends StatelessWidget {

  final _TestText text = new _TestText();

  @override
  Widget build(BuildContext context) {
    return new Column(
        children: [
          text,
          new RaisedButton(
            child: new Text("change"),
            onPressed: () => text.update(),
          ),
        ]
    );
  }
}

class TestText extends StatefulWidget {

  final _TestTextState state = new _TestTextState();

  void update() {
    state.change();
  }

  @override
  _TestTextState createState() => state;
}

class _TestTextState extends State<TestText> {

  String text = "original";

  void change() {
    setState(() {
      this.text = this.text == "original" ? "changed" : "original";
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Text(this.text);
  }
}

Solution 2

thier is no way to do so. any how you have to convert your StatelessWidget to StatefulWidget.

Share:
7,207
Jakub
Author by

Jakub

Updated on December 07, 2022

Comments

  • Jakub
    Jakub over 1 year

    Just testing out flutter. The code sample below is a very simple flutter app. The problem is that I don't know how to call the setState() function inside the TestTextState class in order to change the text each time when the change button is pressed.

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Test app',
          home: new Scaffold(
            appBar: new AppBar(
              title: new Text("Test"),
            ),
            body: new Test(),
          ),
        );
      }
    }
    
    class Test extends StatelessWidget {
    
      final TestText testText = new TestText();
    
      void change() {
        testText.text == "original" ? testText.set("changed") : testText.set("original");
      }
    
      @override
      Widget build(BuildContext context) {
        return new Column(
          children: [
            testText,
            new RaisedButton(
                child: new Text("change"),
                onPressed: () => change(),
            ),
          ]
        );
      }
    }
    
    class TestText extends StatefulWidget {
    
      String text = "original";
    
      void set(String str) {
        this.text = str;
      }
    
      @override
      TestTextState createState() => new TestTextState();
    }
    
    class TestTextState extends State<TestText> {
    
      @override
      Widget build(BuildContext context) {
        return new Text(this.widget.text);
      }
    }
    
  • Jakub
    Jakub over 5 years
    Thanks for the super fast response. Adding the StreamController seems like a good idea. How the solution with no non-final field would look like? Is that even possible?
  • Jakub
    Jakub over 5 years
    Thanks for your replay. So if I have several different pages in my app and all of them share the one dynamic text widget, does it mean that I have to convert all my screens to StatefulWidgets? How would it reflect the performance?
  • Andrey Turkovsky
    Andrey Turkovsky over 5 years
    Store this field inside TestTextState, and inside listen check current value of text- for example. In this case you can send any data to stream - type doesn't matter