Search code examples
flutterdartgoogle-cloud-firestoreriverpodflutter-riverpod

How to solve the infinite loop problem in Flutter?


I get the following error in the terminal (not the debug console because I'm running flutter run -d chrome --web-hostname localhost --web-port 7357 command):

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following JSRangeError was thrown building App(dirty, dependencies: [UncontrolledProviderScope],
state: _AppState#e4a9b):
Invalid argument: Maximum call stack size exceeded

The relevant error-causing widget was:
  App App:file:///Users/user/development/projects/flutter/project/lib/src/project.dart:46:21

When the exception was thrown, this was the stack:
packages/riverpod/src/framework/auto_dispose.dart 7:24                     <computed>
packages/riverpod/src/stream_provider/base.dart 110:56                     __
packages/riverpod/src/stream_provider/auto_dispose.dart 42:7               __
packages/riverpod/src/stream_provider/auto_dispose.dart 31:45              createElement
packages/riverpod/src/framework/container.dart 49:32                       [_create]
packages/riverpod/src/framework/container.dart 41:52                       getElement
packages/riverpod/src/framework/container.dart 455:39                      <fn>
packages/riverpod/src/framework/provider_base.dart 75:25                   addListener
packages/riverpod/src/framework/container.dart 298:20                      listen
packages/flutter_riverpod/src/consumer.dart 506:25                         <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 194:23  putIfAbsent
packages/flutter_riverpod/src/consumer.dart 510:8                          watch
packages/project/src/app.dart 61:34                                         build
packages/flutter/src/widgets/framework.dart 4992:27                        build
packages/flutter_riverpod/src/consumer.dart 488:20                         build
packages/flutter/src/widgets/framework.dart 4878:15                        performRebuild
packages/flutter/src/widgets/framework.dart 5050:11                        performRebuild
packages/flutter/src/widgets/framework.dart 4604:5                         rebuild
packages/flutter/src/widgets/framework.dart 4859:5                         [_firstBuild]
packages/flutter/src/widgets/framework.dart 5041:11                        [_firstBuild]
…
════════════════════════════════════════════════════════════════════════════════════════════════════

I googled this error and saw this answer. This answer says:

You have this error because there is an infinite loop with FeedScreen

I think the point of this answer is "infinite loop".

However, I can't really find where is the infinite loop in the code.

I try to talk about my code structure, I hope everyone can understand. The code in my project, that is, the maintenance code. I can set maintenance to true or false in Firebase Cloud Firestore and then use the flutter_riverpod package to read the maintenance value. If the maintenance value is equal to true, it will show the maintenance screen, otherwise it will show the default screen.

My code:

class MaintenanceModel {
  MaintenanceModel(
    this.id,
    this.isUnderMaintenance,
  );

  final String id;
  final bool isUnderMaintenance;

  factory MaintenanceModel.fromMap(
    Map<String, dynamic> data,
    String documentId,
  ) {
    final bool? isUnderMaintenance = data["isUnderMaintenance"];

    return MaintenanceModel(
      documentId,
      isUnderMaintenance ?? false,
    );
  }
}

Stream<T> documentStream<T>({
    required String path,
    required T Function(Map<String, dynamic> data, String documentID) builder,
  }) {
    DocumentReference<Object?> reference = firestore.doc(path);
    Stream<DocumentSnapshot<Object?>> snapshots = reference.snapshots();
    return snapshots.map((snapshot) => builder(
          snapshot.data() == null
              ? {}
              : snapshot.data() as Map<String, dynamic>,
          snapshot.id,
        ));
  }

Stream<MaintenanceModel> maintenanceStream() {
  return AppServices.kFirestoreService.documentStream(
    path: "Admins/maintenance",
    builder: (data, documentId) => MaintenanceModel.fromMap(data, documentId),
  );
}

final maintenanceProvider = StreamProvider.autoDispose<MaintenanceModel>((ref) {
  final repository = ref.watch(provider);

  return repository.maintenanceStream();
});

final maintenanceValue = ref.watch(maintenanceProvider);

maintenanceValue.when(
  data: (maintenance) => maintenance.isUnderMaintenance ? MaintenanceScreen() : DefaultScreen(),
  error: (error, stackTrace) => const Center(child: Text("Error!")),
  loading: () => const Center(child: CircularProgressIndicator()),
),

If you need more info feel free to leave a comment!

How to solve the infinite loop problem in Flutter? I would appreciate any help. Thank you in advance!


Solution

  • If this on Flutter web, and you call riverpod provider with autoDispose, then its exactly like I was asking here.

    After update to new version, its get fixed.