I am running into this weird issue that the app does not load the page content unless I hit ctrl s in VScode(hot reload).
The following code gets a list of emotion names from the database and loads them onto the screen.
class EmotionListView extends StatefulWidget {
const EmotionListView({Key? key}) : super(key: key);
@override
_EmotionListViewState createState() => _EmotionListViewState();
}
class _EmotionListViewState extends State<EmotionListView> {
List<String> emotionNames = [];
@override
void initState() {
getPrimaries().then((value) => value.forEach((element) {
emotionNames.add(element.name);
}));
super.initState();
}
@override
Widget build(BuildContext context) {
ListTile makeListTile(String emotion) => ListTile(
contentPadding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 15.0),
title: Text(
emotion,
style: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
trailing: const Icon(Icons.keyboard_arrow_right,
color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => PhraseListView(emotion: emotion))),
);
},
);
Card makeCard(String emotion) => Card(
elevation: 8.0,
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration:
const BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeListTile(emotion),
),
);
final makeBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: emotionNames.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(emotionNames[index]);
},
),
);
return Scaffold(
appBar: AppBar(
backgroundColor: const Color.fromRGBO(58, 66, 86, 1.0),
title: const Text('Emotions'),
),
body: makeBody,
);
}
}
Here is before and after I hit ctrl s
I was guessing this happened because I did not use setState(). If setState() is the cause, I am not sure how to use it and why I should use it here.
CodePudding user response:
Your guess that you need to use setState
is correct. The reason setState
is needed is that it takes time to gather the data from the database, in the time that takes, the rest of your page renders in. When you actually receive the data you need to notify a re-render with your new data.
You can implement this by adding a fetchEmotionData
function like the one below.
@override
void initState() {
fetchEmotionData(); //Takes time to grab data and will leave your page empty
super.initState();
}
Future fetchEmotionData() async {
await getPrimaries().then((value) => value.forEach((element) {
emotionNames.add(element.name);
}));
setState(() {});
}