Encountering an infinite loop issue when querying user data containing an array in Firebase via onAuthStateChanged
P粉253518620
2023-08-18 15:16:51
<p>My current environment is ReactJS 18.2.0, running with Firebase 10. </p>
<p>The problem I'm currently having is using onAuthStateChanged to query data about the user when they load or log in to the page. </p>
<p>The following is an example code snippet for a custom service that handles Firebase Auth. </p>
<p>All settings are part of the context and are all useState. </p>
<pre class="brush:js;toolbar:false;">const subscribeToAuthChanges = (
handleAuthChange,
setLoadingState,
setUserRole,
setEmail,
setFirstName,
setIsActive,
setLastName,
setLocation,
setUserID
) => {
onAuthStateChanged(auth, (user) => {
if (user) {
handleAuthChange(user);
FirebaseFirestoreService.getUserData(user.uid).then((data) => {
setUserID(user.uid);
setUserRole(data.role);
setEmail(data.email);
setFirstName(data.firstName);
setIsActive(data.isActive);
setLastName(data.lastName);
setLocation(data.location);
});
setLoadingState(false);
} else {
setLoadingState(false);
}
});
};
</pre>
<p>FirebaseFirestoreService.getUserData() function</p>
<pre class="brush:js;toolbar:false;">const getUserData = async (id) => {
const docRef = doc(db, "users", id);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
return docSnap.data();
} else {
return null;
}
};
</pre>
<p>This should not be run within useEffect, the context was created to handle this.</p>
<pre class="brush:js;toolbar:false;">import React, { useState } from "react";
import FirebaseAuthService from "../Services/FirebaseAuthService";
const FirebaseAuth = React.createContext({
user: null,
loading: true,
role: "",
email: "",
firstName: "",
isActive: false,
lastName: "",
location: "",
userID: "",
});
export const FirebaseAuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [role, setRole] = useState(null);
const [email, setEmail] = useState("");
const [firstName, setFirstName] = useState("");
const [isActive, setIsActive] = useState(false);
const [lastName, setLastName] = useState("");
const [location, setLocation] = useState("");
const [userID, setUserID] = useState("");
const [loading, setLoading] = useState(true);
FirebaseAuthService.subscribeToAuthChanges(
setUser,
setLoading,
setRole,
setEmail,
setFirstName,
setIsActive,
setLastName,
setLocation,
setUserID
);
return (
<FirebaseAuth.Provider
value={{
user,
loading,
role,
email,
firstName,
lastName,
isActive,
location,
userID,
}}
>
{children}
</FirebaseAuth.Provider>
);
};
export default FirebaseAuth;
</pre>
<p>在这个例子中,我缺少一个查询字符串数组的设置函数,然而,以任何方式查询该数组都会导致onAuthStateChanged()不断循环,反复向Firebase发出读取请求。</p>
<p>有没有办法读取数组而不遇到这个问题?</p>
<p>我尝试通过循环遍历数组来避免遇到这个问题,然而,以任何方式查询它都会导致Firebase被反复POST请求。</p>
The reason your loop is running is because you did not set onAuthStateChanged() in the side effect, please try the following