我有一個簡單的表單,注冊用戶并將用戶的用戶名和電子郵件資料發送到Firestore的一個集合,我使用最新版本的Firebase 9 w/模塊化。 認證作業很好,但Firestore部分沒有。它向我拋出了一個錯誤:
TypeError。不能讀取屬性of undefined (讀取'indexOf')
在Function.fromString (path.ts:229)
在Ac2 (reference.ts:374)
在Login.jsx:29.
我不知道那是什么意思,我試圖以 "用戶/(這里是useruid)/所有用戶資料 "的順序將注冊用戶的電子郵件和uid資訊上傳到firestore,但卻拋出了這個錯誤。
我留下我的代碼:
import React, { useState, useEffect, useCallback } from 'react
import { auth, db } from " .../firebase"
import { createUserWithEmailAndPassword } from "firebase/auth"/span>。
import { collection, doc, addDoc, setDoc } from "firebase/firestore"。
function Login(/span>) {
const [email, setEmail] = useState(' ')
const [pass, setPass] = useState(''/span>)
const [error, setError] = useState(''/span>)
const [userData, setUserData] = useState(''/span>)
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(''/span>)
setPass('')
setError('')
} catch (error) {
const errorCode = error.code;
const errorMessage = error.message;
setError(errorMessage)
console.log(error)
}
}, [email, pass, error, userData])
return (
<div>
<h3>/span>Registro</h3>
<form onSubmit={ProcessData}>/span>
<label>電子郵件地址</label>
<input
type="email"
placeholder="email Address"
onChange={e => setEmail(e.target.value)}。
value={email}。
/>
<label>Password</label>
<input
type="password"
placeholder="密碼"
onChange={e => setPass(e.target.value)}。
value={pass}。
/>
<button type="submit"/span>> 注冊</button>。
</form>/span>
</div>
)
}
export default Login)
uj5u.com熱心網友回復:
發行量
Login的第29行: 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(''/span>)。
const [pass, setPass] = useState(''/span>)。
const [error, setError] = useState(''/span>)。
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 } = 錯誤。
setError(message)。
console.log(錯誤)。
}
}
}, [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(''/span>)。
setPass(''/span>)。
setError('')。
} catch (error) {
const { code, message } = 錯誤。
setError(message)。
console.log(錯誤)。
}
}, [email, pass, error, userData])
return (
...
)
}
uj5u.com熱心網友回復:
在添加一個檔案時,你沒有必要從userData狀態中讀取資料。試著直接從user物件中傳遞引數回傳:
try {
const { user } = await createUserWithEmailAndPassword(auth, email, pass)
setUserData(user)
await setDoc(doc(db, ' users', user.uid), {
// ^^^ ^^<-- DocumentReference and not CollectionReference。
email: user.email,
uid: user.uid, uid.
})
} catch (e) {
console.log(e)
}
另外,你在collection()中傳遞了兩個路徑段,這可能會回傳一個錯誤,因為CollectionReference路徑需要奇數的路徑段。如果你想讓用戶的UID作為檔案ID,那么請使用setDoc,因為addDoc將生成一個隨機的ID。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/307001.html
標籤:
