Реагируйте и firebase v9: динамическая настройка пути на onSnapshot не работает

# #reactjs #firebase #google-cloud-firestore

#реагирует на #огневая база #google-облако-firestore

Вопрос:

Прямо сейчас для моего веб-приложения я пытаюсь использовать firebase для отображения данных из моей базы данных в мое приложение. Один из пользователей (пользователи-это коллекция в базе данных) имеет идентификатор QTKVV0WOBMhkq7Q6TPpDsGvprXf1. Идентификатор-это просто идентификатор пользователя (так что CurrentUser.uid). И у каждого пользователя есть набор привычек. Когда я жестко ввожу идентификатор QTKVV0WOBMhkq7Q6TPpDsGvprXf1 в путь, я могу отображать данные из своей базы данных в своем приложении на локальном хосте, но я хочу иметь возможность отображать данные любого пользователя независимо.

Я перепробовал столько способов, сколько мог, но, похоже, просто не могу этого понять. Есть какие-нибудь предложения? Я попытался создать переменную, содержащую текущий идентификатор пользователя.uid, но это не работает. Я пробовал делать и другие вещи, но все это заканчивалось ошибками…

Поэтому в идеале я хотел бы поменять середину пути в onSnapshot, чтобы он просто принимал текущий.uid

 import React, { useEffect, useState } from "react"; import Habit from "./Habit"; import SearchBar from "./SearchBar"; import db, { useAuth } from "../firebase"; import { onSnapshot, collection } from "@firebase/firestore";  const HabitList = ({ mainSection, handleMainSection }) =gt; {  // this initial state will be replaced with API request  const [habits, setHabits] = useState([  // { name: "Sample habit 1", id: 1 },  // { name: "Sample habit 2", id: 2 },  // { name: "Sample habit 3", id: 3 },  ]);   const currentUser = useAuth();  var currentUserPath;  if(currentUser) {  console.log('uid: ', currentUser.uid)  currentUserPath=currentUser.uid;  console.log('currentUser: ', currentUser);  }    useEffect(  () =gt;   onSnapshot(collection(db, `users/QTKVV0WOBMhkq7Q6TPpDsGvprXf1/user_habits`), (snapshot) =gt;   setHabits(snapshot.docs.map((doc) =gt; doc.data()))  //setHabits(snapshot.docs.map((doc) =gt; doc.data())); // make sure that setHabits works and sets snapshot to habits  //console.log(habits); // habits should have the habits from firebase, not the initial habits we hardcoded  ),   []  );    return (  lt;div className="flex flex-col"gt;  lt;SearchBar /gt;  {habits.map(h =gt; (  lt;Habit  habitName={h.name}  handleMainSection={handleMainSection}  key={h.id}  /gt;  ))}  lt;/divgt;  ); };  export default HabitList;  

firebase.js (useAuth)

 // Import the functions you need from the SDKs you need import { useEffect, useState } from "react"; import { initializeApp } from "firebase/app"; import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; import { doc, setDoc } from "firebase/firestore"; import { v4 as uuidv4 } from "uuid"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries  // Your web app's Firebase configuration const firebaseConfig = {  apiKey: "AIzaSyBN30k6RivLOuz7KToi_uD8V5s5cmyD9RM",  authDomain: "auth-development-62c42.firebaseapp.com",  projectId: "auth-development-62c42",  storageBucket: "auth-development-62c42.appspot.com",  messagingSenderId: "414005826367",  appId: "1:414005826367:web:7b987851735426ebedf98a" };  // Initialize Firebase const app = initializeApp(firebaseConfig); const auth = getAuth();  export function signup(email, password) {  return createUserWithEmailAndPassword(auth, email, password); }  export function login(email, password) {  return signInWithEmailAndPassword(auth, email, password); }  // eventually write a logout function  export async function sendHabitToFirestore(uidPath, habitName) {  const db = getFirestore();  const habitId = uuidv4();  const pathDocRef = doc(db, "users", uidPath, "user_habits", habitId);  await setDoc(pathDocRef, {  name: habitName,   id: habitId  }); }  export function useAuth() {  const [currentUser, setCurrentUser ] = useState();  useEffect(() =gt; {  const unsub = onAuthStateChanged(auth, user =gt; setCurrentUser(user));  return unsub;  }, [])   return currentUser; }  export default getFirestore();   

Ошибка:

 Failed to compile ./src/components/HabitList.jsx SyntaxError: C:UsersjojocDesktoplocal_devhabitudesrccomponentsHabitList.jsx: Unexpected token (37:6)   35 | setHabits(newHabits); // consider using snapshot.docChanges() in later renders for efficiency  36 | console.log("New version of habits found!", newHabits); // note: habits isn't updated straight away, so we use the array passed to setHabits gt; 37 | ),  | ^  38 | (error) =gt; {  39 | // TODO: Handle errors!  40 | } This error occurred during the build time and cannot be dismissed.  

Ответ №1:

В зависимости от вашей реализации useAuth , currentUser может быть кратко null , что означает, что при первом рендеринге вы useEffect подключаетесь к users/undefined/user_habits вместо ожидаемого идентификатора пользователя. Поскольку ваш useEffect прослушиватель не прослушивает изменения currentUser , он никогда не будет вызван снова с соответствующим идентификатором пользователя после проверки сеанса.

 useEffect(() =gt; {  if (currentUser == null) { // signed out/not ready  // if habits is already empty, don't trigger a rerender  setHabits(habits.length === 0 ? habits : []);  return;  }    const userDocRef = collection(db, `users/${currentUser.uid}/user_habits`);  return onSnapshot(  userColRef,  (snapshot) =gt; {  const newHabits = snapshot.docs.map((doc) =gt; doc.data());   setHabits(newHabits); // consider using snapshot.docChanges() in later renders for efficiency  console.log("New version of habits found!", newHabits); // note: habits isn't updated straight away, so we use the array passed to setHabits  },  (error) =gt; {  // TODO: Handle errors!  }  ); }, [currentUser]); // rerun if currentUser changes (e.g. validated, signed in/out)  

Комментарии:

1. я попытался скопировать и вставить его в свой код, но он не смог скомпилироваться. я думаю, что это связано с некоторыми синтаксическими ошибками? я обновлю свой пост, чтобы включить в него ошибку.

2. Я также добавил реализацию useAuth на случай, если это будет более полезно, хотя я согласен, что слушатель useEffect, вероятно, не видит изменений в текущем пользователе, поэтому я получаю пользователей/неопределенных/пользователей.

3. На самом деле nvm, я исправил некоторые детали, но в остальном это работает, я верю, спасибо!

4. @outofthegravity Моя вина. Это было ) вместо } «а». Рад помочь.