It looks like you want to call setState inside the onPressed callback of a button in your ListView.builder widget that's inside a FutureBuilder. The problem is that the setState method requires access to the State object of the widget, and you're trying to call it from within the builder function. To achieve this, you need to move the FutureBuilder to a stateful widget and then use setState within that widget.
Here's an example of how you can structure your Flutter code to achieve this
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future<List<dynamic>> _fetchData() async {
// Fetch your data here and return a List<dynamic>
// Example: return BidRepository().bidsTrucker('new');
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<dynamic>>(
future: _fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return const Center(child: Text('Error loading data'));
} else if (!snapshot.hasData || snapshot.data.isEmpty) {
return const Center(child: Text('No data available'));
}
final trips = snapshot.data!;
return ListView.builder(
itemCount: trips.length,
itemBuilder: (context, index) {
final trip = trips[index];
return AcceptBidCard(
// Your AcceptBidCard properties here
onPressed: () {
// Use setState to update the widget's state
setState(() {
// Perform your update logic here
// For example, remove the item from the list:
trips.removeAt(index);
});
},
);
},
);
},
);
}
}
In this code:
MyWidget is a stateful widget that contains the FutureBuilder and the ListView.builder.
_fetchData is a method where you should fetch your data asynchronously. Replace the example code with your actual data fetching logic.
Inside the itemBuilder of the ListView.builder, you can call setState to update the widget's state when the button is pressed. In this example, it removes the item from the list, but you can perform your specific update logic here.
Remember to replace the data fetching logic and other widget properties as per your application's requirements.
If both the parent (the widget containing the FutureBuilder
) and the child (the AcceptBidCard
widget) are already stateful widgets, you can propagate the callback from the parent widget to the child widget without needing to use setState
directly in the child widget. Here's how you can do that:
In your parent widget, define a callback function that you want to execute when the "Accept" button is pressed.
Pass this callback function as a parameter to your child widget.
In the child widget, call this callback function when the "Accept" button is pressed.
Here's an example of how to do this:
In your parent widget (the one containing the FutureBuilder
):
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
// Define a callback function to handle bid acceptance
void handleAcceptBid(String tripId) {
// Perform any necessary logic and updates here
setState(() {
// Update your list or any state variables here
// You can access 'tripId' to identify which bid was pressed
});
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<dynamic>>(
future: BidRepository().bidsTrucker('new'),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final trips = snapshot.data!;
return ListView.builder(
itemCount: trips.length,
itemBuilder: ((context, index) {
final trip = trips[index];
return AcceptBidCard(
fromLocation:
'${trip['from_address']['name']}, ${trip['from_address']['country']}',
toLocation:
'${trip['to_address']['name']}, ${trip['to_address']['country']}',
bidderName: trip['customer_name'],
date: DateFormat('dd-MM-yyyy')
.format(DateTime.parse(trip['trip_date'])),
tripId: trip['trip_id'],
onPressed: () {
// Call the callback function from the parent
handleAcceptBid(trip['trip_id']);
},
);
}),
);
},
);
}
}
In the child widget (AcceptBidCard
), you can use the onPressed
callback to trigger the handleAcceptBid
callback passed down from the parent widget when the "Accept" button is pressed. This way, you're handling state updates in the parent widget's stateful context.