I am trying to use a FutureBuilder with a ListView to display a list of documents from a Firestore db. I am getting errors saying the future: is not defined and the builder: is not defined. I also get an error at the < where I am trying to set the type for the Future builder. That error code is: The operator '<' isn't defined for the type 'Type'.
Here is my code:
class CompanyDashboardScreen extends ConsumerStatefulWidget {
static const String id = 'user_dashboard_screen';
const CompanyDashboardScreen({super.key});
@override
ConsumerState<CompanyDashboardScreen> createState() =>
_CompanyDashboardScreenState();
}
class _CompanyDashboardScreenState
extends ConsumerState<CompanyDashboardScreen> {
bool showSpinner = false;
late List<Map<String, dynamic>> itemsTrxn;
bool isLoaded = false;
Future<List<Map<String, dynamic>>> _getTrxnData() async {
var collectionTrxn = FirebaseFirestore.instance
.collection('company')
.doc(ref.read(globalsNotifierProvider).companyId)
.collection('trxns');
List<Map<String, dynamic>> tempList = [];
// ignore: unused_local_variable
var dataTrxn = await collectionTrxn.get();
dataTrxn.docs.forEach((element) {
tempList.add(element.data());
});
setState(() {
itemsTrxn = tempList;
isLoaded = true;
});
return tempList;
}
@override
void setState(VoidCallback fn) {
_getTrxnData();
super.setState(fn);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: CustomAppBar(),
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: const Text("User Profile"),
onTap: () {
MainScreen.of(context)
?.setIndex(3); // Added this for BottomNavigationBar sync
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const UserProfileScreen()));
},
),
],
),
),
body: SafeArea(
child: FutureBuilder < <<< ERROR
Map<String, dynamic>(
ERROR >>> future: FirebaseFirestore.instance
.collection('company')
.doc(ref.read(globalsNotifierProvider).companyId)
.collection('trxns')
.get(),
ERROR >>> builder: isLoaded
? ListView.builder(
itemCount: itemsTrxn.length,
itemBuilder: (context, index) {
//_getTrxnData(); // Get the list of trxns
return Padding(
padding: cont EdgeInsets.all(8.0),
child: ListTile(
isThreeLine: true,
title: Row(
children: [
Text(
'Client: ${itemsTrxn[index]['clientFName'] ?? 'n/a'} ${itemsTrxn[index]['clientLName'] ?? 'n/a'}',
style: const TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueAccent),
),
],
),
subtitle: Text.rich(
TextSpan(
text:
'${itemsTrxn[index]['propertyAddress'] ?? 'n/a'}, '
'${itemsTrxn[index]['propertyCity'] ?? 'n/a'}, '
'${itemsTrxn[index]['propertyState'] ?? 'n/a'}',
children: <TextSpan>[
TextSpan(
text:
'\nPrice: ${itemsTrxn[index]['contractPrice'] == null ? 'n/a' : NumberFormat.simpleCurrency().format(itemsTrxn[index]['contractPrice'])}\nStatus: ${itemsTrxn[index]['trxnStatus'] ?? 'n/a'}',
style: const TextStyle(
fontWeight: FontWeight.w900,
color: Colors.blueGrey),
)
],
),
),
trailing: Text(
'MLS#: ${itemsTrxn[index]['mlsNumber'] ?? 'n/a'}\n${itemsTrxn[index]['clientType']}'),
onTap: () {
//MainScreen.of(context)?.setIndex(2); // Added this for BottomNavigationBar sync
ref
.read(globalsNotifierProvider.notifier)
.updatenewTrxn(false);
ref
.read(globalsNotifierProvider.notifier)
.updatecurrentTrxnId(
itemsTrxn[index]['trxnId']);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
TransactionDetailScreen(
itemsTrxn[index]['trxnId'])));
},
),
);
},
)
: const Text('No Date'),
),
),
),
);
}
}
What am I doing wrong to get these errors and how do I fix this? Thanks
Error 1:
You missed a >
Your code
FutureBuilder<Map<String, dynamic>(...)
Fixed code
FutureBuilder<Map<String, dynamic>>(...)
Error 2:
builder is not just a widget, is a callback that returns a widget and is of type (BuildContext context, AsyncSnapshot<Map<String, dynamic>> snapshot) => myWidget()
builder: (context, snapshot) {
return isLoaded ? ListView.builder(....) : const Text('No Date');
}
And as a side note, if you're already loading outside of the future builder there is no need to use that
PS2: Don't override setState and a put a future callback _getTrxnData()
inside, it will make a recursion because _getTrxnData
uses setState inside, which will call _getTrxnData
again and so on. Use Riverpod to make the computation inside the provider