无法使用 Firebase v9 Modular React JS 读取未定义的属性(读取'indexOf')
我得到了这个简单的表单,用于注册用户并将 uid 和电子邮件数据发送到 firestore 上的集合,我使用的是最新版本的 Firebase 9 w/ 模块化。 身份验证工作正常,但 firestore 部分不行。它抛出一个错误:
TypeError: Cannot read properties of undefined (reading 'indexOf')
at Function.fromString (path.ts:229)
at Ac2 (reference.ts:374)
at Login.jsx:29
我不知道那是什么意思,我试图将注册用户的电子邮件和 uid 信息上传到 firestore,顺序为“用户/(这里是用户 uid)/所有用户数据”,但抛出了那个错误。
我留下我的代码:
import React, { useState, useEffect, useCallback } from 'react'
import { auth, db } from "../firebase"
import { createUserWithEmailAndPassword } from "firebase/auth";
import { collection, doc, addDoc, setDoc } from "firebase/firestore";
function Login() {
const [email, setEmail] = useState('')
const [pass, setPass] = useState('')
const [error, setError] = useState('')
const [userData, setUserData] = useState('')
const ProcessData = e => {
e.preventDefault()
registro()
}
const registro = useCallback(async() => {
try {
await createUserWithEmailAndPassword(auth, email, pass)
.then((userCredential) => {
const user = userCredential.user;
setUserData(user)
})
await addDoc(collection(db, 'users', userData.uid), {
email: userData.email,
uid: userData.uid
})
setEmail('')
setPass('')
setError('')
} catch (error) {
const errorCode = error.code;
const errorMessage = error.message;
setError(errorMessage)
console.log(error)
}
}, [email, pass, error, userData])
return (
<div>
<h3>Registro</h3>
<form onSubmit={ProcessData}>
<label>Email Adress</label>
<input
type="email"
placeholder="Email Address"
onChange={e => setEmail(e.target.value)}
value={email}
/>
<label>Password</label>
<input
type="password"
placeholder="Password"
onChange={e => setPass(e.target.value)}
value={pass}
/>
<button type="submit">Registrarse</button>
</form>
</div>
)
}
export default Login
添加文档时,您不一定需要从
userData
状态读取数据。尝试直接从返回的
user
对象传递参数,这样
doc()
中的任何路径段都不会未定义:
try {
const { user } = await createUserWithEmailAndPassword(auth, email, pass)
setUserData(user)
// db must not be undefined
// try console.log(db) to ensure it's a Firestore instance
await setDoc(doc(db, 'users', user.uid), {
// ^^^ ^^^<-- DocumentReference and not CollectionReference
email: user.email,
uid: user.uid
})
} catch (e) {
console.log(e)
}
此外,您在
collection()
中传递了 2 个路径段,这可能会返回错误,因为 CollectionReference 路径采用奇数个路径段。如果您希望将用户的 UID 作为文档 ID,请使用
setDoc
,因为
addDoc
将生成一个随机 ID。
问题
Line 29 of Login: await addDoc(collection(db, 'users', userData.uid), {
userData.uid
可能是罪魁祸首,因为
userData
仍然是初始空字符串 (
''
) 状态值。请记住,React 状态更新是异步处理的,因此当
setUserData(user)
在
collection(db, 'users', userData.uid)
中引用以下几行时,它尚未更新
userData
状态。
解决方案
我建议将
registro
函数的后半部分拆分为一个
useEffect
钩子,并依赖于
userData
状态以发出添加文档的副作用。
function Login() {
const [email, setEmail] = useState('');
const [pass, setPass] = useState('');
const [error, setError] = useState('');
const [userData, setUserData] = useState(null);
useEffect(() => {
if (userData) {
const { email, uid } = userData;
try {
addDoc(collection(db, 'users', uid), { email, uid });
} catch (error) {
const { code, message } = error;
setError(message);
console.log(error);
}
}
}, [userData]);
const ProcessData = e => {
e.preventDefault();
registro();
}
const registro = useCallback(async() => {
try {
await createUserWithEmailAndPassword(auth, email, pass)
.then((userCredential) => {
const { user } = userCredential;
setUserData(user);
});
setEmail('');
setPass('');
setError('');
} catch (error) {
const { code, message } = error;
setError(message);
console.log(error);
}
}, [email, pass, error, userData])
return (
...
)
}