Home > Back-end >  The method 'when' isn't defined for the type 'Object'
The method 'when' isn't defined for the type 'Object'

Time:05-25

I created this StateNotifier with Riverpod in Flutter which Returns the Object DocumentsList

class TripStateNotifier extends StateNotifier<List<DocumentList>> {
  TripStateNotifier() : super([]);
  void getDocuments() async {
    final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');
    state = res as List<DocumentList>;
  }
}

final TripState = StateNotifierProvider((ref) => TripStateNotifier());

And this ConsumerWidget whicht gets the data

 ref.watch(TripState)!.when(
                  data: (list) {
                    //Handeling if no data is found
                    if(list == null || (list.documents?.isEmpty ?? true)) return Center(child: Text("Yet you didn´t add any destinations to your trip", style: TextStyle(color: Colors.black.withOpacity(0.5)))); return ListView.builder(
                      itemCount: list.total,
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemBuilder: (context, index) {
                        return mytrip_card(
                          location: list.documents[index].data['location'], date: list.documents[index].data['date']
                        );
                      },
                    );
                  },
                  error: (e, s) => Text(e.toString()),
                  loading: () => const CircularProgressIndicator(),
                ),

My Problem is that my IDE Outputs following Error in regards to the when in ref.watch(TripState)!.when

The method 'when' isn't defined for the type 'Object'.

Intrestingly enought my Old Soulution with Future Provider worked why does this not?

Old solution:

final TripProvider = FutureProvider((ref)
async {
    debugPrint('test');
    final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');

    return res;
});

CodePudding user response:

Define StateNotifier like this

final tripState = StateNotifierProvider<TripStateNotifier, List<DocumentList>>((ref) {
  return TripStateNotifier();
});

Access to documents like this

List<DocumentList> trips = ref.watch(tripState);
return ListView.builder(
  itemCount: trips.length,
  itemBuilder: (context, index) {
...
  }
);

See StateNotifierProvider for details.

CodePudding user response:

The method when is only available for the object type AsyncValue which can be provided by a FutureProvider or a StreamProvider. Now that you are using a StateNotifierProvider, you won't be able to use when anymore, I would recommend you to create a "state" class to use with your TripStateNotifier.

Code sample:

final tripStateProvider = StateNotifierProvider<TripStateNotifier, TripState>(
    (ref) => TripStateNotifier());

class TripStateNotifier extends StateNotifier<TripState> {
  TripStateNotifier() : super(const TripState());

  void getDocuments() async {
    // Trigger the loading state
    state = state.copyWith(isLoading: true);

    try {
      final res = await db.listDocuments(collectionId: '6286c0f1e7b7a5760baa');
      // Update the state with your newly fetched results
      state = state.copyWith(
        isLoading: false,
        documents: res as List<DocumentList>,
      );
    } catch (e) {
      // Manage received error
      state = state.copyWith(
        isLoading: false,
        hasError: true,
      );
    }
  }
}

@immutable
class TripState {
  final bool isLoading;
  final bool hasError;
  final List<DocumentList> documents;

  const TripState({
    this.documents = const [],
    this.isLoading = false,
    this.hasError = false,
  });

  int get total => documents.length;

  TripState copyWith({
    List<DocumentList>? documents,
    bool? isLoading,
    bool? hasError,
  }) {
    return TripState(
      documents: documents ?? this.documents,
      isLoading: isLoading ?? this.isLoading,
      hasError: hasError ?? this.hasError,
    );
  }
}

class MyWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final currentState = ref.watch(tripStateProvider);

    if (currentState.isLoading) return const CircularProgressIndicator();

    if (currentState.documents.isEmpty) {
      return Center(
        child: Text(
          "Yet you didn´t add any destinations to your trip",
          style: TextStyle(
            color: Colors.black.withOpacity(0.5),
          ),
        ),
      );
    }
    return ListView.builder(
      itemCount: currentState.total,
      scrollDirection: Axis.vertical,
      shrinkWrap: true,
      itemBuilder: (context, index) {
        return MyTripCard(
          location: currentState.documents[index].data['location'],
          date: currentState.documents[index].data['date'],
        );
      },
    );
  }
}

Try the full example on DartPad

  • Related