Passing Data to a Stateful Widget

Mojachiee picture Mojachiee · Jun 12, 2018 · Viewed 77.9k times · Source

I'm wondering what the recommended way of passing data to a stateful widget, while creating it, is.

The two styles I've seen are:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState(_server);
}

class _ServerInfoState extends State<ServerInfo> {
  Server _server;

  _ServerInfoState(Server server) {
    this._server = server;
  }
}

This method keeps a value both in ServerInfo and _ServerInfoState, which seems a bit wasteful.

The other method is to use widget._server:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState();
}

class _ServerInfoState extends State<ServerInfo> {
  @override
    Widget build(BuildContext context) {
      widget._server = "10"; // Do something we the server value
      return null;
    }
}

This seems a bit backwards as the state is no longer stored in _ServerInfoSate but instead in the widget.

Is there a best practice for this?

Answer

R&#233;mi Rousselet picture Rémi Rousselet · Jun 12, 2018

Don't pass parameters to State using it's constructor. You should only access these using this.widget.myField.

Not only editing the constructor requires a lot of manual work ; it doesn't bring anything. There's no reason to duplicate all the fields of Widget.

EDIT :

Here's an example:

class ServerIpText extends StatefulWidget {
  final String serverIP;

  const ServerIpText ({ Key key, this.serverIP }): super(key: key);

  @override
  _ServerIpTextState createState() => _ServerIpTextState();
}

class _ServerIpTextState extends State<ServerIpText> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.serverIP);
  }
}

class AnotherClass extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ServerIpText(serverIP: "127.0.0.1")
    );
  }
}