# #reactjs #firebase #google-cloud-firestore
Вопрос:
Я получил эту простую форму, которая регистрирует пользователей и отправляет данные uid и электронной почты в коллекцию в firestore, используя последнюю версию Firebase 9 w/ modular. Аутентификация работает отлично, но часть 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 с порядком «пользователи / (и здесь идентификатор пользователя)/ все данные пользователя», но выдает мне эту ошибку.
Я оставляю свой код:
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
Комментарии:
1. В предоставленном вами фрагменте кода нет вызова кода
.indexOf
. Конечно, к ошибке прилагается трассировка стека, которая сообщает вам, откуда произошла ошибка. Можете ли вы обновить свой вопрос, чтобы включить полное сообщение об ошибке и трассировку стека?2. @DrewReese я обновляю все сообщение об ошибке, которое меня выбрасывает, проверьте это c:
3. добавьте часть вашего кода, в которой вы вызываете
.indexOf
4. Что такое строка 29
Login
компонента?5. Привет @PeterO. Это то, что нигде в моем коде я не использую indexOf, я не могу найти строку кода, где она ссылается на «indexOf».
Ответ №1:
Вам не обязательно считывать данные из 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
})
} catch (e) {
console.log(e)
}
Кроме того, вы передавали 2 сегмента пути, в collection()
которых может быть возвращена ошибка, так как путь ссылки на коллекцию занимает нечетное количество сегментов пути. Если вам нужен идентификатор UID пользователя в качестве идентификатора документа, используйте setDoc
, так addDoc
как он сгенерирует случайный идентификатор.
Комментарии:
1. Ах, гораздо проще, чем мое решение. Я чувствую себя почти глупо, что не видел этого. Почет.
2. Спасибо! Я не часто использую React, но всякий раз, когда я это делаю, я отдаю приоритет обработке данных над состоянием :’)
Ответ №2:
Вопрос
Строка 29 входа в систему: ожидание addDoc(коллекция(бд, «пользователи», userData.uid), {
userData.uid
скорее всего, виновник, так userData
как по-прежнему является начальным значением состояния пустой строки ( ''
). Помните, что обновления состояния реакции обрабатываются асинхронно, поэтому setUserData(user)
они еще не обновили userData
состояние, когда на него ссылаются несколько строк ниже collection(db, 'users', userData.uid)
.
Решение
Я предлагаю разделить вторую половину 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 (
...
)
}