Abrufen von Benutzerdaten aus der Benutzersammlung beim Anmelden

Nov 21 2020

Ich arbeite derzeit an einer Anwendung mit Firebase, die auf der Clientseite initialisiert wurde. Wenn sich ein Benutzer über Firebase anmeldet, möchte ich die Daten des Benutzers aus dem Firestore abrufen. Ich mache dies derzeit im onAuthStateChangedListener und rufe den Benutzer erfolgreich ab. Ich frage mich, ob dies der beste Weg ist, um die Benutzerdaten abzurufen. Mein Code lautet wie folgt:

  const [currentUser, setCurrentUser] = useState(null)
  const [authState, setAuthState] = useState(false)

  useEffect(() => {
    console.log('state unknown')
    setAuthState(false)
    auth().onAuthStateChanged(user => {
      if (!user) {
        return
      }
      const sourceRef = firestore()
        .collection('users')
        .where('userId', '==', user.uid)
      sourceRef
        .get()
        .then(snapshot => {
          if (snapshot.empty) {
            console.log('user not found')
          } else {
            let data = {}
            snapshot.forEach(item => (data = item.data()))
            console.log(data)
            setCurrentUser(data)
            setAuthState(true)
          }
        })
        .catch(error => console.log(error.code))
    })
  }, [])

  return (
    <AppContext.Provider value={{ currentUser, authState }}>
      {children}
    </AppContext.Provider>
  )
}

Mein Hauptanliegen ist, dass die Daten des Benutzers jedes Mal abgerufen werden, wenn die Anwendung aktualisiert wird. Anregungen oder Best Practices zu diesem Thema sind sehr willkommen

Antworten

2 LouisCoulet Nov 21 2020 at 17:55

Meiner Meinung nach ist Ihr Ansatz mit der Kontext-API und dem Auth-Beobachter bereits gut, mit nur geringfügigen Problemen:

  • Sie sollten Ihre Beobachter wie von Awran5 erwähnt abbestellen
  • Sie können Benutzerdaten beobachten, anstatt sie nur einmal abzurufen
  • Sie können Ihre Kontexte nach Lesbarkeit und Leistung trennen
  • Sie können Ihre Dokumente in Sammlungsbenutzern mit der ID des Eigentümers erstellen, sodass Sie direkt darauf zugreifen können, collection("users").doc(authUser.uid)anstatt eine Abfrage durchzuführen

Hier ist, wie ich Ihr Beispiel ändern würde, nicht sicher, ob es der beste Weg ist, ich erwarte auf andere Kommentare:

const AuthContext = React.createContext();

function AuthProvider({ children }) {
    const [authUser, setAuthUser] = React.useState(undefined);

    React.useEffect(() => {
        return firebase.auth().onAuthStateChanged(user => setAuthUser(user));
    }, []);

    return <AuthContext.Provider value={authUser}>{children}</AuthContext.Provider>;
}
const UserDataContext = React.createContext();

function UserDataProvider({ children }) {
    const [userData, setUserData] = React.useState(null);
    const authUser = React.useContext(AuthContext);

    React.useEffect(() => {
        if (!authUser) return;
        const query = firebase.firestore().collection("/users").where("userId", "==", authUser.uid);
        return query.onSnapshot(snapshot => setUserData(snapshot.empty ? null : snapshot.docs[0].data()));
    }, [authUser]);

    return <UserDataContext.Provider value={userData}>{children}</UserDataContext.Provider>;
}
export default function App() {
    return (
        <AuthProvider>
            <UserDataProvider>
                {/* ... other components */}
                <MyComponent />
            </UserDataProvider>
        </AuthProvider>
    );
}
function MyComponent() {
    const authUser = React.useContext(AuthContext);
    const userData = React.useContext(UserDataContext);
    if (authUser === undefined) return <div>loading user authentication...</div>;
    if (authUser === null) return <div>logged out</div>;
    return <div>User data: {JSON.stringify(userData)}</div>;
}

Ihre Komponenten werden bei Änderung des Authentifizierungsstatus oder bei Änderung der Benutzerdaten weiterhin neu gerendert, jedoch nur nach Bedarf.