web-dev-qa-db-fra.com

Émettre les données au parent Widget dans Flutter

J'essaie de définir le texte du widget enfant au widget parent. Mais le texte ne reflète pas dans le widget parent.

Essayé d'utiliser setState () également mais toujours incapable d'obtenir le résultat attendu.

Voici mon code:

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

class TestApp extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<TestApp>{

  String abc = "";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Column(
          children: <Widget>[
            new Text("This is text $abc"),
            TestApp2(abc)
          ],
        ),
      ),
    );
  }
}


class TestApp2 extends StatefulWidget {

  String abc;

  TestApp2(this.abc);

  @override
  _TestState2 createState() => new _TestState2();
}

class _TestState2 extends State<TestApp2>{
  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 150.0,
      height: 30.0,
      margin: EdgeInsets.only(top: 50.0),
      child: new FlatButton(
          onPressed: (){
            setState(() {
              widget.abc = "RANDON TEXT";
            });
          },
        child: new Text("BUTTON"),
        color: Colors.red,
      ),
    );
  }
}

Est-ce que je manque quelque chose?

13
Tushar Pol

Dans votre exemple, quelques hypothèses ont été formulées. Je vais essayer d'enlever un par un.

  1. Vous passez abc de parent en enfant et vous avez muté la valeur de l’enfant en appuyant sur le bouton. Comme les types primitifs sont transmission par valeur dans Dart, une modification de la valeur de abc dans un enfant ne modifiera pas la valeur du parent abc. Reportez-vous à l'extrait ci-dessous.

    void main() {
      String abc = "newValue";
      changeIt(abc);
      print(abc); // newValue
    }
    
    void changeIt(String abc) {
      abc = "newValue";
      print(abc); //newValue
    }
    
  2. Supposons que le premier est faux (pour la compréhension du but). Ensuite, changer la valeur de abc dans enfant modifiera la valeur de abc dans parent. Mais sans appeler cela à l'intérieur de setState de parent, parent ne reflétera pas le changement. Dans votre cas, si vous modifiez le code comme ci-dessous, le texte du bouton ne sera modifié que lorsque vous cliquerez (comme on appelle setState of child).

    new FlatButton(
        onPressed: (){
        setState(() {
            widget.abc = "RANDON TEXT";
        });
        },
        child: new Text(widget.abc), // setting the text based on abc
        color: Colors.red,
    )
    
  3. Au lieu d'utiliser globalState qui sera très difficile à maintenir/à déboguer à mesure que l'application grandit, je vous recommande d'utiliser callbacks. Veuillez vous reporter au code ci-dessous.

    void main() => runApp(new TestApp());
    
    class TestApp extends StatefulWidget {
    @override
    _TestState createState() => new _TestState();
    }
    
    class _TestState extends State<TestApp>{
    
    String abc = "bb";
    
    callback(newAbc) {
        setState(() {
        abc = newAbc;
        });
    }
    
    @override
    Widget build(BuildContext context) {
        var column = new Column(
            children: <Widget>[
                new Text("This is text $abc"),
                TestApp2(abc, callback)
            ],
            );
        return new MaterialApp(
        home: new Scaffold(
            body: new Padding(padding: EdgeInsets.all(30.0),child: column),
        ),
        );
    }
    }
    
    class TestApp2 extends StatefulWidget {
    
    String abc;
    Function(String) callback;
    
    TestApp2(this.abc, this.callback);
    
    @override
    _TestState2 createState() => new _TestState2();
    }
    
    class _TestState2 extends State<TestApp2>{
    @override
    Widget build(BuildContext context) {
        return new Container(
        width: 150.0,
        height: 30.0,
        margin: EdgeInsets.only(top: 50.0),
        child: new FlatButton(
            onPressed: (){
                widget.callback("RANDON TEXT"); //call to parent
            },
            child: new Text(widget.abc),
            color: Colors.red,
        ),
        );
    }
    }
    
25

Le point qui vous manque est votre appel à la méthode setState. Vous appelez le setState du TestState2.

Pour résoudre ce problème, il y a deux façons.

La première consiste à créer une clé GlobalKey ( https://docs.flutter.io/flutter/widgets/GlobalKey-class.html ) et à la transmettre en tant que paramètre au widget enfant.

Et la deuxième méthode consiste à créer une variable globale pour l’état parent et à l’utiliser dans l’état enfant.

J'ai modifié le code ci-dessous avec la deuxième approche.

_TestState _globalState = new _TestState();

class TestApp extends StatefulWidget {
  @override
  _TestState createState() => _globalState;
}

class _TestState extends State<TestApp>{

  String abc = "";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Column(
          children: <Widget>[
            new Text("This is text $abc"),
            TestApp2()
          ],
        ),
      ),
    );
  }
}


class TestApp2 extends StatefulWidget {

  TestApp2();

  @override
  _TestState2 createState() => new _TestState2();
}

class _TestState2 extends State<TestApp2>{
  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 150.0,
      height: 30.0,
      margin: EdgeInsets.only(top: 50.0),
      child: new FlatButton(
        onPressed: (){
          _globalState.setState((){
            _globalState.abc = "Button clicked";
          });
        },
        child: new Text("BUTTON"),
        color: Colors.red,
      ),
    );
  }
}
4
salihguler