Josh Kahane
Josh Kahane

Reputation: 17169

Flutter - setState Not Using New Data

I have a screen which I pass data back to like so:

final myUpdatedObject = await Navigator.of(context).push(...);
setState({
  object = myUpdatedObject;
});

Having checked with a simple print at all places in my widget body that my object is used, the new data is present after it is passed back by the Navigator and setState is called.

However, when the widget is rebuilt, even though the new data is apparently there, it is not reflected in the UI changes, it shows old data.

Is this some sort of caching in debug mode? Whats causing this issue?

Upvotes: 0

Views: 1773

Answers (1)

Albert Lardizabal
Albert Lardizabal

Reputation: 6856

The example below starts with a Map named textMessageMap with a message key that populates a Text Widget with 'Home'. Tap the FloatingActionButton and you'll navigate to SecondScreen. If you tap the 'Go back!' button in SecondScreen, the message key in textMessageMap will be updated to read 'Second Screen'. If you tap the back button on the Scaffold of SecondScreen, textMessageMap will be nulled out. Calling setState updates the UI appropriately. See if your implementation is different.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  Map<String, String> textMessageMap = {'message': 'Home'};

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              '${textMessageMap != null ? textMessageMap['message'] : 'map is null'}',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          _launchSecondScreen();
        },
        child: new Icon(Icons.add),
      ),
    );
  }

  _launchSecondScreen() async {
    final value = await Navigator.push(
        context,
        MaterialPageRoute<Map<String, String>>(
            builder: (BuildContext _) => SecondScreen()));
    setState(() {
      textMessageMap = value;
    });
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack. The text 'Second Screen' will replace 'Home'.
            // If you hit the scaffold's back button, the return value will be
            // null instead.
            final map = {'message': 'Second Screen'};
            Navigator.pop(context, map);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

Upvotes: 1

Related Questions