React Native迁移Firebase至Database类后出现'undefined is not an object'错误求助
解决React Native中Database类方法报错及导航问题
问题原因分析
你遇到的undefined is not an object (evaluating 'this.codesRef.once')错误主要有两个核心原因:
checkCode被定义成了静态方法(带static关键字),静态方法属于类本身而非类的实例,自然无法访问实例属性this.codesRef;- 你调用时直接用
db.checkCode(这里的db是Database类,不是实例),进一步导致实例属性完全无法被访问。
另外还有一个隐藏的异步逻辑坑:你把codeIsFound的判断写在了firebase.database().ref().once()的回调外面,而once是异步操作,回调还没执行完就会先运行外面的判断,导致结果永远不正确。
解决方案
1. 修改Database.js:转为实例方法+单例模式
把静态方法改为实例方法,同时将Database类导出为单例,确保整个应用使用同一个数据库实例:
var firebase = require('firebase'); if (!firebase.apps.length) { firebase.initializeApp({ apiKey: "key", authDomain: "domain", databaseURL: "url", storageBucket: "bucket", }); } class Database { constructor() { // 将codesRef初始化放到构造函数中,确保实例创建时就完成初始化 this.codesRef = firebase.database().ref('codes'); } // 去掉static关键字,转为实例方法 checkCode(text, navigation) { let codeIsFound = false; let identifier = ''; this.codesRef.once('value', (db_snapshot) => { db_snapshot.forEach((code_snapshot) => { if (text === code_snapshot.val().value) { codeIsFound = true; identifier = code_snapshot.key; } }); // 将判断逻辑移到回调内部,确保异步操作完成后再执行 if (codeIsFound) { // this.deleteCode(identifier); console.log("code found"); navigation.navigate('Create'); } else { console.log("code not found"); } }); }; } // 导出单例实例,避免重复创建Database对象 const dbInstance = new Database(); module.exports = dbInstance;
2. 修改KeyForm.js:传入导航参数并调用实例方法
现在导入的是Database的单例实例,直接调用实例方法,并把组件的navigation属性传进去:
import React from 'react'; import { StyleSheet, View, TextInput } from 'react-native'; import db from '../Database.js'; // 现在导入的是单例实例 class LoginForm extends React.Component { render() { return ( <View style={styles.container}> <TextInput placeholder="Access Code" returnKeyType="go" onSubmitEditing={(text) => { // 把组件的navigation传入checkCode方法 db.checkCode(text.nativeEvent.text, this.props.navigation) }} /> </View> ); } } const styles = StyleSheet.create({ // 你的样式定义 }); export default LoginForm;
额外说明
- 导航问题:不需要使用
withNavigation,直接将组件的this.props.navigation作为参数传递给checkCode即可,这样Database类就能调用导航方法了; - 异步操作:Firebase的数据库操作都是异步的,所有依赖操作结果的逻辑必须放在回调函数(或者使用Promise/async-await)内部,否则会拿到未更新的变量值。
内容的提问来源于stack exchange,提问作者Michael Hoefler
相关产品推荐
相关产品推荐

