Firestore每次重载应用创建新用户致历史数据丢失问题排查
应用重启后丢失Firebase匿名凭证、生成新用户问题修复
核心问题原因
你的代码存在3处直接导致认证状态丢失的错误:
- 未导入Firebase核心库,仅导入了auth、firestore的兼容插件,运行时全局
firebase对象缺失,认证持久化逻辑完全失效 - 认证状态监听逻辑时序错误:
onAuthStateChanged在SDK初始化阶段首次触发时必然返回null(此时SDK还未完成本地缓存凭证的读取),你的逻辑检测到null就立刻调用匿名登录,直接覆盖了本地可能存在的旧用户凭证,强制生成新用户 - 未显式配置React Native环境下的Firebase Auth持久化策略,默认配置不会将匿名用户凭证写入本地存储,应用关闭后凭证直接被清除
另外App.js中存在冗余代码:重复定义了两次renderList方法,且将Fire实例赋值给全局变量存在引用丢失风险。
修复步骤
1. 修正Fire.js代码
首先补全Firebase核心导入,添加持久化配置,调整认证监听逻辑:
// 补全核心库导入 import firebase from 'firebase/compat/app'; import 'firebase/compat/firestore'; import 'firebase/compat/auth'; const firebaseConfig = { // 填入你自己的Firebase配置项 }; class Fire { constructor(callback) { this.init(callback); } init(callback) { if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); } // 显式设置本地持久化,凭证将存储在设备本地,重启应用不丢失 firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL) .then(() => { firebase.auth().onAuthStateChanged(user => { if (user) { // 已存在登录用户(包括本地缓存的匿名用户),直接返回 callback(null, user); } else { // 无有效用户时才发起新的匿名登录 firebase .auth() .signInAnonymously() .catch(error => { callback(error); }); } }); }) .catch(err => callback(err)); } getLists(callback) { let ref = this.ref.orderBy('name'); this.unsubscribe = ref.onSnapshot(snapshot => { const lists = []; // 补全变量声明,避免隐式全局变量污染 snapshot.forEach(doc => { lists.push({ id: doc.id, ...doc.data() }); }); callback(lists); }); } addList(list) { let ref = this.ref; ref.add(list); } updateList(list) { let ref = this.ref; ref.doc(list.id).update(list); } deleteList(list) { let ref = this.ref; ref.doc(list.id).delete(); } get userId() { return firebase.auth().currentUser.uid; } get ref() { return firebase .firestore() .collection('users') .doc(this.userId) .collection('lists'); } detach() { // 增加空判断,避免未初始化时调用报错 if (this.unsubscribe) { this.unsubscribe(); } } } export default Fire;
2. 修正App.js代码
将Fire实例挂载到组件实例上避免全局污染,删除冗余的重复方法定义:
// 其余导入保持不变 export default class App extends React.Component { state = { addTodoVisibile: false, lists: [], user: {}, loading: true, }; componentDidMount() { // 将firebase实例挂载到组件this上,不要用全局变量 this.firebase = new Fire((error, user) => { if (error) { return alert('Something went wrong'); } this.firebase.getLists(lists => { this.setState({ lists, user, loading: false }); }); this.setState({ user }); }); } componentWillUnmount() { this.firebase.detach(); } toggleAddTodoModal() { this.setState({ addTodoVisibile: !this.state.addTodoVisibile }); } addList = list => { this.firebase.addList({ name: list.name, color: list.color, todos: [], }); }; updateList = list => { this.firebase.updateList(list); }; deleteList = list => { this.firebase.deleteList(list); }; // 删除之前重复定义的第一个renderList,只保留带deleteList参数的版本 renderList = list => { return ( <TodoList list={list} updateList={this.updateList} deleteList={this.deleteList} /> ); }; // render方法和样式部分保持原有代码不变即可 }
验证说明
修复后首次启动应用会生成一个匿名用户,该用户的凭证会被持久化存储在设备本地。后续关闭重开应用时,SDK会自动读取本地凭证恢复登录状态,直接拉取对应用户下存储的笔记列表,不会再生成新用户。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

