You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firestore.instance.collection调用报‘undefined’错误求助

问题分析与解决方案

问题概述

在以下代码位置触发undefined报错:

FirebaseAuth auth = FirebaseAuth.instance;
await Firestore.instance.collection('users').document(auth.currentUser.uid).setData({
  'levelTestTaken': true,

已导入Firebase相关依赖,但问题未解决,完整代码如下:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'app/modules/auth_service/auth_controller/auth_controllers.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/splash',
      routes: {
        '/splash': (context) => SplashPage(),
        '/login': (context) => LoginPage(),
        '/level_test': (context) => LevelTestPage(),
        '/main': (context) => MainPage(),
      },
    );
  }
}

class SplashPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder(
          future: _navigateToAppropriatePage(context),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return Container();
            } else {
              return CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }

  Future<void> _navigateToAppropriatePage(BuildContext context) async {
    FirebaseAuth auth = FirebaseAuth.instance;
    if (auth.currentUser == null) {
      Navigator.pushNamed(context, '/login');
    } else {
      DocumentSnapshot userDoc = await Firestore.instance.collection('users').document(auth.currentUser.uid).get();
      bool levelTestTaken = userDoc.data['levelTestTaken'];
      if (levelTestTaken) {
        Navigator.pushNamed(context, '/main');
      } else {
        Navigator.pushNamed(context, '/level_test');
      }
    }
  }
}

class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Login Page'),
      ),
    );
  }
}
class LevelTestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            // Save the levelTestTaken information to the user's document in the Firestore database
            FirebaseAuth auth = FirebaseAuth.instance;
            await Firestore.instance.collection('users').document(auth.currentUser.uid).setData({
              'levelTestTaken': true,
            }, merge: true);
            Navigator.pushNamed(context, '/main');
          },
          child: Text('Complete Level Test'),
        ),
      ),
    );
  }
}

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Main Page'),
      ),
    );
  }
}

问题原因

  • 用户状态未同步:Splash页的判断逻辑仅读取单次auth.currentUser,跳转至LevelTestPage时,用户认证状态可能因异步更新变为null,导致访问uid触发undefined错误。
  • Firestore API版本兼容:代码使用旧版Firestore API(document()、setData()),在新版SDK中这些方法已废弃,存在兼容性问题。
  • 字段/文档未初始化:若用户文档不存在或levelTestTaken字段未定义,直接读取会引发异常。

解决方案

1. 安全校验用户状态

在访问用户ID前强制做非空校验,避免空指针:

onPressed: () async {
  FirebaseAuth auth = FirebaseAuth.instance;
  User? user = auth.currentUser;
  if (user != null) {
    await FirebaseFirestore.instance.collection('users').doc(user.uid).set({
      'levelTestTaken': true,
    }, SetOptions(merge: true));
    Navigator.pushNamed(context, '/main');
  } else {
    Navigator.pushNamed(context, '/login');
  }
},

2. 升级Firestore API到最新规范

替换旧版API为当前官方推荐用法:

  • Firestore.instance → FirebaseFirestore.instance
  • document() → doc()
  • setData() → set(),用SetOptions(merge: true)替代原merge参数

3. 优化用户状态监听逻辑

使用authStateChanges()实时监听用户状态,确保获取最新认证信息:

Future<void> _navigateToAppropriatePage(BuildContext context) async {
  FirebaseAuth auth = FirebaseAuth.instance;
  User? user = await auth.authStateChanges().first;
  if (user == null) {
    Navigator.pushNamed(context, '/login');
  } else {
    DocumentSnapshot userDoc = await FirebaseFirestore.instance.collection('users').doc(user.uid).get();
    bool levelTestTaken = userDoc.data()?['levelTestTaken'] ?? false;
    if (levelTestTaken) {
      Navigator.pushNamed(context, '/main');
    } else {
      Navigator.pushNamed(context, '/level_test');
    }
  }
}

4. 初始化用户文档处理

若用户文档不存在,先创建默认文档再读取:

DocumentSnapshot userDoc = await FirebaseFirestore.instance.collection('users').doc(user.uid).get();
if (!userDoc.exists) {
  await FirebaseFirestore.instance.collection('users').doc(user.uid).set({
    'levelTestTaken': false,
    // 添加其他必要默认字段
  });
}
bool levelTestTaken = userDoc.data()?['levelTestTaken'] ?? false;

内容的提问来源于stack exchange,提问作者jonghwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:45:29