我正在尝试使用 React Native Firebase 构建一个简单的 android 应用程序,用于监听 onAuthStateChanged 的身份验证。如果我理解正确的话,onAuthStateChanged 方法有多个状态,所以它会多次触发 useEffect。问题是我想在身份验证后触发一个函数,检查用户是否包含在 firebase 数据库中,但由于这个原因,该函数将被多次触发,并且当我在onAuthStateChanged 函数。
const [userDetails, setUserDetails] = useState();
const [initializing, setInitializing] = useState(true);
function onAuthStateChanged(user) {
if (user !== null) {
setUserDetails({
name: user.displayName,
email: user.email,
photo: user.photoURL,
theme: 'default',
});
if (initializing) setInitializing(false);
checkUserInDB()
} else {
setUserDetails(null);
setInitializing(true);
}
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
为了克服这个问题,我可以调用 checkUserInDb() 函数,方法是将它留在 onAuthStateChanged 之外,等待 userDetails 并完成初始化状态:
if (userDetails !== null && initializing === false) {
checkUserInDb()
虽然这将返回 userDetails,但如果我记录它,它会发生 3 次。我试图从几个角度(等待/然后/超时)解决它,但问题出在 useEffect 中,我只是没有想法。如果你能指出正确的方向,我将不胜感激。
我花了几个小时弄清楚这个问题,我成功地克服了它。我相信
onAuthStateChanged
不喜欢我尝试使用上面的 userDetails 设置自定义状态。通过像文档中那样使用用户,我没有返回 undefined 。但它仍然不是问题的解决方案,因为它确实会在 onAuthStateChanged 解决之前运行 2-3 次。我发现了另一个 thread,其中有人使用了我实现的去抖动,并且对我的原始逻辑进行了一些重构,它开始工作了。
var debounceTimeout;
const DebounceDueTime = 200; // 200ms
function onAuthStateChanged(user) {
if (debounceTimeout) clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() => {
debounceTimeout = null;
handleAuthStateChanged(user);
}, DebounceDueTime);
}
function handleAuthStateChanged(user) {
setUser(user);
if (initializing) setInitializing(false);
if (user !== null) {
console.log('=========> User is authenticated already:', user);
checkUserInDb(user);
} else {
console.log('=========> User not found or signed out:', user);
}
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);