anfeu
anfeu

Reputation: 43

Call setState outside of a StatefulWidget (with a setter)

I have a lot of experience with Javascript and now I want to start with Flutter. So maybe my problem is that I see the code as JS developer and the Flutter solution would be different. But here is my problem: I want to create a simple card game. A playing card is a StatefulWidget:

class GameCard extends StatefulWidget {

  int _value;
  String _suit;
  bool _visible;

  String _imagePath;

  // void setVisible() {
  //   How to execute setState here??
  // }

  GameCard({int value, String suit, bool visible = false}) {
    ...
    this._visible = visible;
    this._value = value;
    this._suit = suit;
  }

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

class _GameCardState extends State<GameCard> {

  String getSuit() => widget._suit;
  int getValue() => widget._value;

  bool isVisible() => widget._visible;

  @override
  Widget build(BuildContext context) {
  ...
  return ClipRRect(
      borderRadius: BorderRadius.circular(10),
      child: Container(
        width: width,
        height: width * 1.5,
        decoration: BoxDecoration(
          image: DecorationImage(
            fit: BoxFit.cover,
            image: AssetImage(widget._imagePath), 
      ...

The idea is that the imagePath in the state class should be a image of a card back when the card is not visible. Now I want to have a setVisible function in my StatefulWidget which runs setState() followed by an update of the imagePath. After that imagePath should be a image of a playing card like for example hearts king. So finally I want to create an instance of GameCard somewhere else and change the image with a setter:

GameCard spadeFour = GameCard(value: 4, suit: 'spade', visible: false),
spadeFour.setVisible(true)

How can I do that? I read about Globalkey and other stuff but it can't be that complicated cause this is a very common use case.

Upvotes: 3

Views: 2541

Answers (1)

Alex Schneider
Alex Schneider

Reputation: 384

Generally you should avoid instantiating a widget and then modifying it through properties. This is also unnecessary since you already correctly use parameters to change the appearance of the widget.

To get the widget to redraw with different parameters, instead of calling setState within that widget, call it in the parent widget.

class _YourParentPageState extends State<YourParentPage> {

  bool visible = false;

  _changeVisibility(bool v) {
    setState(() {
      visible = v;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return GameCard(value: 4, suit: 'spade', visible: visible);
  }
}

Calling _changeVisibility will redraw your GameCard with the updated visible parameter.

Upvotes: 4

Related Questions