我尝试在身份验证后将firestore与我的react项目一起使用,以将一些数据写入firebase。但是每当调用doc.set
时,我都会收到一个错误消息,说Cannot read property firestore of null
。
这是我的firebase配置文件。
import firebase from 'firebase/app';
const config = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
};
if (firebase.apps.length === 0) {
console.log('Initializing firebase');
firebase.initializeApp(config);
}
export default firebase;
这是我的firebase utils文件,可用于从firebase访问常见需求。
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import {FIREBASE_COLLECTIONS} from './constants';
export const getIdToken = async () => {
try {
const {currentUser} = firebase.auth();
if (currentUser) {
const idToken = await currentUser.getIdToken();
return idToken;
}
return currentUser;
} catch (error) {
throw error || new Error('Error retrieving ID token');
}
};
export const logout = async () => {
try {
await firebase.auth().signOut();
} catch (error) {
throw error || new Error('Error logging out');
}
};
export const loginUser = async (email: string, password: string) => {
try {
const user = await firebase
.auth()
.signInWithEmailAndPassword(email, password);
return user;
} catch (error) {
let message = '';
switch (error.code) {
case 'auth/invalid-email':
message = 'Invalid Email Id';
break;
case 'auth/user-disabled':
message = 'User is temporarily disabled';
break;
case 'auth/user-not-found':
message = 'User not found. Please register';
break;
case 'auth/wrong-password':
message = 'Incorrect password';
break;
default:
message = 'Error logging in';
break;
}
throw new Error(message);
}
};
export const registerUser = async (email: string, password: string) => {
try {
const user = await firebase
.auth()
.createUserWithEmailAndPassword(email, password);
return user;
} catch (error) {
const errorCode = error.code;
let message = '';
switch (errorCode) {
case 'auth/email-already-in-use':
message = 'Email already in use';
break;
case 'auth/invalid-email':
message = 'Invalid email ID';
break;
case 'auth/weak-password':
message = 'Weak password';
break;
default:
message = 'Error registering user';
break;
}
throw new Error(message);
}
};
export const signInWithGoogle = async () => {
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({prompt: 'select_account'});
const scopes = ['profile', 'email'];
scopes.forEach(scope => provider.addScope(scope));
try {
return await firebase.auth().signInWithPopup(provider);
} catch (error) {
let message = '';
switch (error.code) {
case 'auth/account-exists-with-different-credential':
message = 'Account exists with another sign in type';
break;
case 'auth/popup-closed-by-user':
message = 'Login popup closed';
break;
default:
message = 'Error signing in';
break;
}
throw new Error(message);
}
};
export const isLoggedIn = (): boolean => {
const {currentUser} = firebase.auth();
return currentUser !== null;
};
export const getUserDoc = (
id: string
): firebase.firestore.DocumentReference => {
return firebase
.firestore()
.collection(FIREBASE_COLLECTIONS.USERS)
.doc(id);
};
export default firebase;
我正在从firebase utils调用getUserDoc函数,并使用该函数将数据写入用户。
function* registerWithPassword(user: UserInput) {
try {
const userData: firebase.auth.UserCredential = yield call(
registerUser,
user.email,
user.password
);
if (userData === null || userData.user === null) {
yield put(
authFailureAction.failure({
register: 'Unable to register user',
})
);
} else {
const userDoc = getUserDoc(userData.user.uid);
yield call(
userDoc.set,
{labels: [], pinnedNotes: [], name: user.name},
{merge: true}
);
}
} catch (e) {
console.log({e});
yield put(
authFailureAction.failure({
register: e.message || 'Unable to register user',
})
);
}
}
调用userDoc.set
时,会发生错误。
通过一些调试,firebase看起来为空。这就是firebase.firestore()
引发错误的原因。
但是,如果firebase为null,则auth也不能正常工作,但是firebase auth没有任何问题。
还要注意,我正在firebaseConfig.js
文件中导入index.js
,所以我确定firebase已初始化。这也是由于用户正在注册,但由于某些原因,当我从firestore
访问firebase.firestore()
时,firebase
为空。
您可以访问项目here。尝试注册用户,您将看到错误。由于它取决于Firebase,因此您必须添加一个相关的.env
文件。
答案 0 :(得分:2)
由于在文件中而不是在单个模块中进行多个Firebase导入/导出的问题,因此可能会发生错误。
firebase
模块只能在firebase_config
文件中导出,然后从那里导入其他文件。
因此,在firebase_utils
中,您可以添加而不是:
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import firebase from './firebase-config.js';
您还可以从export default firebase;
中删除firebase_utils
,以防止firebase
命名空间被覆盖。
因此,最终的firebase_config.js
文件可能如下所示:
// Firebase App (the core Firebase SDK)
var firebase = require("firebase/app");
// Add the Firebase products that you want to use
require("firebase/auth");
require("firebase/firestore");
// Your app's Firebase project configuration
var firebaseConfig = {
// ...
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
// Single source for all imports of the firebase module
export default firebase;
对于firebase
的导入示例,您也可以参考this article和this GitHub repo。
答案 1 :(得分:1)
您必须使用已初始化的Firebase。
import firebase from 'firebase/app'; <-- This one hasn't been initialized.
...
firebase.initializeApp(firebaseConfig);
export default firebase; <-- This one is initialized.
在您的firebase_config中,添加firestore并进行身份验证
import firebase from 'firebase/app';
import 'firebase/auth'; <----- add this here.
import 'firebase/firestore'; <----- add this here.
const config = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
};
if (firebase.apps.length === 0) {
console.log('Initializing firebase');
firebase.initializeApp(config);
}
export default firebase;
更改前3行。
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import {FIREBASE_COLLECTIONS} from './constants';
export const getIdToken = async () => {
try {
const {currentUser} = firebase.auth();
if (currentUser) {
const idToken = await currentUser.getIdToken();
....
到
import firebase from './firebase_config.js'; // or wherever your firebase.initializeApp(...) live.
import {FIREBASE_COLLECTIONS} from './constants';
export const getIdToken = async () => {
try {
const {currentUser} = firebase.auth();
if (currentUser) {
const idToken = await currentUser.getIdToken();
....
美好的一天。