Shiv Patel
Shiv Patel

Reputation: 23

State does not update until button is pressed twice

I am trying to learn and work with APIs, I am using the Tiingo Stock API to get stock info. My current app is:

class _StockAppState extends State<StockApp> {


String out = "Enter Ticker and press Submit";
  Map<String,String> headers = {
        'Content-Type': 'application/json',
        'Authorization' : <API KEY REMOVED>
        };

  void getPrice(String tick) async {
    if(tick == ""){
      out = "Enter Ticker and press Submit";
    }else{
      Response rep = await get('https://api.tiingo.com/tiingo/daily/$tick/prices', headers: headers);
    if(rep.statusCode ==  200){  
      List data = json.decode(rep.body);
      Map dataS = data[0];
      out = "Price: ${dataS['close']}";
    }else{
      out = "Error";
    }
    }
  }

  @override
  void initState() { 
    super.initState();  
  }

  TextEditingController ticker = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Stock App'),),
      body: Column(
          children: <Widget>[
            TextField(
              controller: ticker,
              textAlign: TextAlign.left,
              decoration: InputDecoration(
                border: InputBorder.none,
                hintText: 'Enter Ticker',
                hintStyle: TextStyle(color: Colors.grey),
              ),
            ),
            FlatButton(
              onPressed: () async {
                FocusScope.of(context).unfocus();
                setState(() {
                  getPrice(ticker.text);
                });
              },
              child: Text('Submit')
            ),
            Text(out),  
          ],
        ),
    );
  }
}

So, basically, when you enter a ticker and press submit, the app will change the "out" string var to display the stock price. But for the app to update, I am having to press submit twice.

Could anyone help?

P.S.: I have removed my API key for security reasons.

Upvotes: 0

Views: 702

Answers (1)

mahesh
mahesh

Reputation: 4763

It is because you have async method in your setState method. The setState method will be called synchronously.

So here problem is when setState is performed and frame get refreshed your data from api has not arrived yet and it showing you the old data. When you again click the button your out variable have new data (from your first click) which will be shown on the screen and API will be called again.

To solve your problem

       FlatButton(
          onPressed: () async {
            FocusScope.of(context).unfocus();
            await getPrice(ticker.text);
            setState(() {
              
            });
          },
          child: Text('Submit')
        ),

So call the setState method after API call is completed.

To know more about async/await watch this video : https://www.youtube.com/watch?v=SmTCmDMi4BY

Upvotes: 1

Related Questions