Récupération des données utilisateur de la collection d'utilisateurs lors de la connexion
Je travaille actuellement sur une application avec firebase initialisé côté client. Lorsqu'un utilisateur se connecte via Firebase, je souhaite récupérer les données de l'utilisateur depuis le firestore. Je le fais actuellement dans l' onAuthStateChanged
auditeur et je récupère avec succès l'utilisateur. Je me demande si c'est la meilleure façon de récupérer les données utilisateur. Mon code est le suivant:
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>
)
}
ma principale préoccupation est que les données de l'utilisateur seront récupérées chaque fois que l'application est actualisée. Toutes suggestions ou meilleures pratiques en la matière seraient grandement appréciées
Réponses
À mon humble avis, votre approche utilisant l'API contextuelle et l'observateur d'authentification est déjà bonne, avec seulement des problèmes mineurs:
- vous devez désinscrire vos observateurs comme mentionné par Awran5
- vous pouvez observer les données utilisateur au lieu de les récupérer une seule fois
- vous pouvez séparer vos contextes pour plus de lisibilité et de performance
- vous pouvez créer vos documents dans les utilisateurs de la collection avec l'identifiant du propriétaire, vous pouvez donc accéder directement au
collection("users").doc(authUser.uid)
lieu de faire une requête
Voici comment je modifierais votre exemple, je ne sais pas si c'est le meilleur moyen, j'attends les autres commentaires:
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>;
}
Vos composants seront toujours rendus lors du changement d'état d'authentification ou de la modification des données utilisateur, mais uniquement si nécessaire.