I'm pretty new to Flutter and I've come across an issue when working with Future types. Basically, I'm trying to develop a simple search engine that displays books which have the query string in the title in a List View. Using Future Builder, I get a list with all the books from a raw JSON file and, if the snapshot has data, I pass it through the searchBooks
function, that takes in the query
string and gather the search results in an array. Finally, I would pass the book data to the bookCard
function that actully builds the display.
The issue I've been having is that I can't work with the snapshot data because Class 'Future<List<dynamic>>' has no instance of method '[]'
.
How would I go about fixing this?
Here is the JSON data I've beeen working with, for reference: https://raw.githubusercontent.com/a-starck02/book_data/main/bookData_complex.json
Here is the part of the code that is throwing the error:
@override
Widget build(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
child: ListView.separated(
scrollDirection: Axis.vertical,
separatorBuilder: (context, index) => SizedBox(width: 8),
itemCount: 15,
**itemBuilder: (BuildContext context, int index) => FutureBuilder(
future: userBooksAll,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData) {
searchBooks(query) async {
var searchResults = [];
for(var i = 0 ; i <= snapshot.data.length ; i ) {
if(snapshot.data[i].title.toLowerCase().contains(query.toLowerCase())) {
searchResults.add(snapshot.data[i]);
}
};
return searchResults;
}
var searchResults = searchBooks(query);
return bookCard(context, searchResults, index factor);**
} else {
return Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: CircularProgressIndicator(),
),
),
);
}
}
),
),
);
}
CodePudding user response:
In dart, only Maps {"key":"value"}
have the []
property, for accessing key, value pairs like somemap["key"]["value"]
For lists the value at the index somelist[index]
This might help https://flutter.dev/docs/cookbook/networking/fetch-data#4-fetch-the-data
CodePudding user response:
Answer
So, the issue that I was having was that the searchBooks
function was async so, naturally, it would return another Future value. It was a pretty silly mistake that I only realized after completely rewriting the code two times.
Anyway, thanks for everyone who spent time thinking about an answer. Here is the final reformatted working code:
@override
Widget build(BuildContext context) {
var itemCount = 0;
return Container(
height: MediaQuery.of(context).size.height,
child: FutureBuilder(
future: userBooksAll,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.hasData) {
bookSearch(query) {
var searchResults = [];
for (var i = 0; i <= snapshot.data.length - 1 ; i ) {
if (snapshot.data[i].title.toLowerCase().contains(
query.toLowerCase())) {
searchResults.add(snapshot.data[i]);
}
}
itemCount = searchResults.length;
return searchResults;
}
var searchResults = bookSearch(query);
return ListView.separated(
scrollDirection: Axis.vertical,
separatorBuilder: (context, index) => SizedBox(width: 8),
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) => bookCard(context, searchResults, index)
);
} else {
return Container(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: CircularProgressIndicator(),
),
);
}
}
)
);
}