skip to Main Content

In a Flutter Web Application, I was trying to print the results of a Supabase query. The results are printed but only after a short flicker/red screen which is due to an error that is printed in the backend/command line. Also if I pressed the Back button, it will show the error.

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following _TypeError was thrown building Builder:
TypeError: null: type 'Null' is not a subtype of type 'String'

The relevant error-causing widget was:
  Builder
  Builder:file:///C:/xxxxxx/Local/Pub/Cache/hosted/pub.dev/go_router-13.2.0/lib/src/builder.dart:249:9

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3       throw_
dart-sdk/lib/_internal/js_shared/lib/rti.dart 1385:3                              _failedAsCheck
dart-sdk/lib/_internal/js_shared/lib/rti.dart 1363:3                              _generalAsCheckImplementation
packages/surveyweb/main.dart 31:45                                                <fn>
packages/go_router/src/builder.dart 250:21                                        <fn>
packages/flutter/src/widgets/basic.dart 7698:48                                   build
packages/flutter/src/widgets/framework.dart 5550:22                               build
packages/flutter/src/widgets/framework.dart 5480:15                               performRebuild
packages/flutter/src/widgets/framework.dart 5196:7                                rebuild
packages/flutter/src/widgets/framework.dart 5556:5                                update
packages/flutter/src/widgets/framework.dart 3824:14                               updateChild
packages/flutter/src/widgets/framework.dart 6765:14                               update
packages/flutter/src/widgets/framework.dart 3824:14                               updateChild
packages/flutter/src/widgets/framework.dart 5505:16                               performRebuild
...

I am a newbie in Flutter and most likely it is due to the handling of Futures and null safety. Kindly check my code and please suggest how to fix it or give a better approach. The page should get all the questions in the Supabase database then print it in the screen. This should never be null.

class Question {
  final int id;
  final String questionText;
  final String? questionId;
  final int mainCategoryId;
  final int? subCategoryId;

  Question(
      {required this.id,
      required this.questionText,
      this.questionId,
      required this.mainCategoryId,
      this.subCategoryId});

  Question.fromJson(Map<String, dynamic> json)
      : id = json['id'],
        questionText = json['question_text'],
        questionId = json['question_id'],
        mainCategoryId = json['main_category_id'],
        subCategoryId = json['sub_category_id'];
}
class QuestionRepository {
  final supabase = Supabase.instance.client;

  Future<List<Question>> getQuestions() async {
    try {
      final response = await supabase.from('questions').select();

      if (response.isNotEmpty) {
        final questions =
            response.map((data) => Question.fromJson(data)).toList();

        return questions;
      } else {
        throw Exception('Failed to fetch questions!!');
      }
    } catch (error) {
      throw Exception('Error fetching questions: $error');
    }
  }
}
class SurveyForm extends StatefulWidget {
  const SurveyForm({super.key});

  @override
  State<SurveyForm> createState() => _SurveyFormState();
}

class _SurveyFormState extends State<SurveyForm> {
  final QuestionRepository _questionRepository = QuestionRepository();
  late Future<List<Question>> _questions;

  Future<void> _fetchQuestions() async {
    try {
      final question = _questionRepository.getQuestions();

      setState(() {
        _questions = question;
      });
    } catch (error) {
      const SnackBar(
        content: Text('Unexpected Error'),
      );
    }
  }

  @override
  void initState() {
    super.initState();
    _fetchQuestions();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Survey"),
        ),
        body: FutureBuilder<List<Question>?>(
          future: _questions,
          builder: (context, snapshot) {
            if (snapshot.hasData &&
                snapshot.connectionState == ConnectionState.done) {
              return ListView.builder(
                itemCount: snapshot.data!.length,
                itemBuilder: (context, index) {
                  return Text(snapshot.data?[index].questionText ?? " ");
                },
              );
            } else {
              return const CircularProgressIndicator();
            }
          },
        ));
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    I have found the error. It was not related to this page, but from a previous page. I was trying to pass an argument/parameter between pages using go_router. Sorry for the trouble.


  2. You can use the getQuestions() directly, no need to call it in initState as FutureBuilder will call it on build() method:

    FutureBuilder(
        future: _questionRepository.getQuestions(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return const Center(child: Text(snapshot.error.toString()));
          } else if (snapshot.hasData) {
            final questions = snapshot.data!;
    
            return ListView.builder(
              itemCount: questions.length,
              itemBuilder: (context, index) {
                return Text(questions.length.toString());
              },
            );
          } else {
            return const Text('No data available');
          }
        },
      )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search