using Riverpod to display data from a multiple api request

316 Views Asked by At

So I have a function that concurrently fetches two diffrent object models , but i'm having a problem trying to display these values by their respective models . So below is where I'm fetching the data that I want to display:

final getProfileAndItem = FutureProvider.family((ref, String uid) async {
  return ref.watch(itemUserProvider).getItemByUser(uid);
});

 Future<(UserTable, ItemModel)> getItemByUser(String uid) async {
    try {
      final value = await Future.wait([
        http.get(Uri.parse('${API.getpurchaseItemByUID}' '?uid=$uid')),
        http.get(Uri.parse('${API.getUserProfileByUID}' '?uid=$uid'))
      ]);

      final item = jsonDecode(value[0].body); 
      final profile = jsonDecode(value[1].body);

      return (UserTable.fromJson(profile[0]), ItemModel.fromJson(item[0]));
    } catch (error) {
      throw error;
    }
  }

Below is where i'm trying to display the data and where i'm getting the error ,it seems that every time I try to fetch a value by the model it belongs to I get The getter isn't defined for the type '(UserTable, itemModel)'.

 ref.watch(getProfileAndItem(uid)).when(
              data: (data) => Column(
                  children: [
                    Text(data.userName),//UserTable
                    Text(data.itemName)//ItemModel
                  ],
                ),
              error: (error, stackTrace) => ErrorText(error: error.toString()),
              loading: () => const Loader(),
            ));
2

There are 2 best solutions below

0
On

Since you are using Record, you can access the record item using the named parameter. For Example:

final getProfileAndItem = FutureProvider.family((ref, String uid) async {
  return ref.watch(itemUserProvider).getItemByUser(uid);
});

 Future<({UserTable userTable, ItemModel itemModel})> getItemByUser(String uid) async {
    try {
      final value = await Future.wait([
        http.get(Uri.parse('${API.getpurchaseItemByUID}' '?uid=$uid')),
        http.get(Uri.parse('${API.getUserProfileByUID}' '?uid=$uid'))
      ]);

      final item = jsonDecode(value[0].body); 
      final profile = jsonDecode(value[1].body);

      return (userTable: UserTable.fromJson(profile[0]), itemModel: ItemModel.fromJson(item[0]));
    } catch (error) {
      throw error;
    }
  }

Then you can use it as:

 ref.watch(getProfileAndItem(uid)).when(
          data: (data) => Column(
              children: [
                Text(data.userTable.userName),//UserTable
                Text(data.itemModel.itemName)//ItemModel
              ],
            ),
          error: (error, stackTrace) => ErrorText(error: error.toString()),
          loading: () => const Loader(),
        ));
5
On

Since data is a Record (type '(UserTable, itemModel)'), if you want to get userName and itemName from the ItemModel (which is the second value in the Record), you should access them like this:

data: (data) => Column(
  children: [
    Text(data.$2.userName),
    Text(data.$2.itemName)
  ],
),