【问题标题】:React and firebase v9: dynamically setting path on onSnapshot doesn't workReact 和 firebase v9:在 onSnapshot 上动态设置路径不起作用
【发布时间】:2022-01-05 00:55:05
【问题描述】:

现在,对于我的 web 应用程序,我正在尝试使用 firebase 将数据库中的数据呈现到我的应用程序中。其中一个用户(用户是数据库中的一个集合)的 id 为 QTKVV0WOBMhkq7Q6TPpDsGvprXf1。 id 只是一个用户 id(所以 currentUser.uid)。 每个用户都有一个习惯集合。当我将 id QTKVV0WOBMhkq7Q6TPpDsGvprXf1 硬编码到路径中时,我可以在本地主机的应用程序中显示我的数据库中的数据,但无论如何我都希望能够显示任何用户的数据。

我已经尝试了尽可能多的方法,但我似乎无法弄清楚。有什么建议?我尝试制作一个包含 currentUser.uid 的变量,但这不起作用。 我尝试过做其他事情,但都以错误告终...

所以理想情况下,我想在 onSnapshot 中换掉路径的中间,以便它只接收 current.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 }) => {
  // 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(
    () => 
    onSnapshot(collection(db, `users/QTKVV0WOBMhkq7Q6TPpDsGvprXf1/user_habits`), (snapshot) => 
      setHabits(snapshot.docs.map((doc) => doc.data()))
      //setHabits(snapshot.docs.map((doc) => 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 (
    <div className="flex flex-col">
      <SearchBar />
      {habits.map(h => (
        <Habit
          habitName={h.name}
          handleMainSection={handleMainSection}
          key={h.id}
        />
      ))}
    </div>
  );
};

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(() => {
    const unsub = onAuthStateChanged(auth, user => setCurrentUser(user));
    return unsub;
  }, [])

  return currentUser;
}

export default getFirestore();

错误:

Failed to compile
./src/components/HabitList.jsx
SyntaxError: C:\Users\jojoc\Desktop\local_dev\habitude\src\components\HabitList.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
> 37 |       ),
     |       ^
  38 |       (error) => {
  39 |         // TODO: Handle errors!
  40 |       }
This error occurred during the build time and cannot be dismissed.

【问题讨论】:

    标签: reactjs firebase google-cloud-firestore


    【解决方案1】:

    根据您对useAuth 的实现,currentUser 可能会简称为null,这意味着在第一次渲染时,您的useEffect 会附加到users/undefined/user_habits,而不是您期望的用户ID。因为您的 useEffect 侦听器不会侦听对 currentUser 的更改,所以一旦会话得到验证,就永远不会使用正确的用户 ID 再次调用它。

    useEffect(() => {
      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) => {
          const newHabits = snapshot.docs.map((doc) => 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) => {
          // TODO: Handle errors!
        }
      );
    }, [currentUser]); // rerun if currentUser changes (e.g. validated, signed in/out)
    

    【讨论】:

    • 我尝试将其复制粘贴到我的代码中,但编译失败。我认为这是由于一些语法错误?我会更新我的帖子以包含错误。
    • 我还添加了 useAuth 的实现以防万一,虽然我同意 useEffect 监听器可能没有看到 currentUser 的更改,所以我得到了 users/undefined/user_habits。
    • 实际上是 nvm,我修复了一些部分,但我相信它可以正常工作,谢谢!
    • @outofthegravity 我的错。它有) 而不是}。很高兴能提供帮助。
    猜你喜欢
    • 2021-11-18
    • 1970-01-01
    • 2021-12-12
    • 2020-10-11
    • 2023-02-21
    • 2018-01-10
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    相关资源
    最近更新 更多