Reactjs React Linking.addEventListener在useEffect中运行Firebase登录链接两次
我具有以下功能,可使用React Native(Expo)和Firebase对用户进行身份验证:Reactjs React Linking.addEventListener在useEffect中运行Firebase登录链接两次,reactjs,firebase,react-native,Reactjs,Firebase,React Native,我具有以下功能,可使用React Native(Expo)和Firebase对用户进行身份验证: export default function AuthenticateUser() { const user = useStore((state) => state.user); // Gets the user from state const setUser = useStore((state) => state.setUser); const setLoadingUs
export default function AuthenticateUser() {
const user = useStore((state) => state.user); // Gets the user from state
const setUser = useStore((state) => state.setUser);
const setLoadingUser = useStore((state) => state.setLoadingUser);
const [GQL_getOrCreateUser] = useMutation(getOrCreateUser); // GraphQL function
useEffect(() => {
let unsubscribe: any;
let urlHandler: any;
function handleUrl(event: any) {
const { url }: { url: string } = event;
if (url.includes('/account')) {
const isSignInWithEmailLink = firebase.auth().isSignInWithEmailLink(url);
if (isSignInWithEmailLink) {
AsyncStorage.getItem('unverifiedEmail').then((email) => {
if (email) {
firebase
.auth()
.signInWithEmailLink(email, url)
.then(() => {
// We are signed in
})
.catch((error) => {
// Failed to sign in
});
} else {
// Missing pending email from AsyncStorage
}
});
}
};
}
function handleLinking(userDetails: User) {
urlHandler = ({ url }: { url: string }) => {
handleUrl({ url, userDetails });
};
// Listen to incoming deep link when app first opens
Linking.getInitialURL().then((url) => {
if (url) {
handleUrl({ url, userDetails });
}
});
// Listen to incoming deep link while app is open
Linking.addEventListener('url', urlHandler);
}
if (!user) {
unsubscribe = firebase.auth().onAuthStateChanged((authenticatedUser) => {
setLoadingUser(false);
if (authenticatedUser) {
const uid = authenticatedUser.uid;
const phoneNumber = authenticatedUser.phoneNumber;
let email: string;
if (authenticatedUser.email) {
email = authenticatedUser.email;
} else {
// retreiving email from AsyncStorage. We add it there when requesting a passwordless sign in link email, as recommended by Firebase.
AsyncStorage.getItem('unverifiedEmail').then((unverifiedEmail) => {
email = unverifiedEmail ? unverifiedEmail : '';
});
}
const emailVerified = authenticatedUser.emailVerified;
// Updating user record with GraphQL
GQL_getOrCreateUser({ variables: { uid, phoneNumber } })
.then(async (document) => {
const data = document.data.getOrCreateUser;
const userDetails = { ...data, phoneNumber, email, emailVerified }
setUser(userDetails); // Setting the stateful user record
handleLinking(userDetails); // Handle deeplink
})
.catch(() => {
// GraphQL failed
});
}
});
}
return () => {
unsubscribe?.();
// Removing event listener;
Linking.removeEventListener('url', urlHandler);
};
}, [GQL_getOrCreateUser, setLoadingUser, setUser, user]);
}
我的问题是sign-in方法运行太频繁,导致意外行为。
我怀疑这是由用户身份验证状态和GraphQL运行触发的重新渲染引起的(GraphQL调用获取或创建用户会导致三次渲染,这似乎是它的行为方式)
我使用deeplinking处理无密码电子邮件登录(firebase.auth().isSignInWithEmailLink(url)
)
使用Linking.getInitialURL(当深度链接打开应用程序时)或Linking.addEventListener('URL',handler)
在应用程序已经运行时检测URL
以场景1为例:Linking.getInitialUrl
if(!user)
中的代码getInitialURL
,它会正确执行步骤并让我登录。
但是,handleLinking
运行第二次(可能是GraphQL引发的额外两次渲染触发了一个Linking.addEventListener
event to fire?)并返回一个错误,因为无法再次使用登录链接谢谢你的帮助 如果
useffect
依赖项中的任何对象发生更改,则useffect
函数将重新运行。因此,如果useffect
回调运行得太频繁,那么应该查看依赖项数组
重要的是要知道,“更改”可以是一个简单的过程,例如重新实例化一个对象或重新创建一个函数,即使基础值保持不变。我在useEffect中看不到任何依赖项@FotisTsakiris看起来更好。它就在那里:
[GQL\u getOrCreateUser,setLoadingUser,setUser,user]
我意识到最有可能的核心问题是依赖关系。我也提到过。我想看看是否有人有一个不同的逻辑,这将更好地工作,并解释他们将如何做不同的想法。