I think I should ask this question, cause I face some very weird problem.
I have a protected route, /app, if user is not login reached this page, redirect to /auth/login, so I have this, common Context hooks:
const { user, isLoading } = useAuth()
useEffect(() => {
if (!(user || isLoading)) {
// HERE REDIRECT TO /auth/login
}
}, [user, isLoading])
//here make sense
Now in my useAuth(), I have this:
const useAuth = () => {
const [user, setUser] = useState(null)
useEffect(() => {
firebase.auth().onAuthStateChanged((currentUser) => {
setIsLoading(false)
if (currentUser) {
console.log(currentUser)
//here
getUserFromMyServer(currentUser.uid).then(res => {
let userDetails = res.detail
setUser(userDetails) // here will get User data from server
}).catch(error => setUser(null))
} else {
setUser(null)
}
})
}, [])
return {
user,
isLoading,
loginWithTwitter, // a function will mention later
getTwitterRedirectResult, //a function will mention later
logout // a function
}
}
This is what I call to server
// here is the getUserFromMyServer function in another files, it look like this:
export const getUserFromMyServer = async () => {
const path = "/user"
const firebaseToken = await firebase.auth().currentUser.getIdToken()
console.log(firebaseToken)
const myInit = {
headers: {
Authorization: `Bearer ${firebaseToken}`,
}
}
return API.get(apiName, path, myInit) // Here return a promise
}
OK, so far is working well. When done login, it will setUser(), then will redirect from /auth/login to /app according to the user, this is what I want.
Now when I implement Sign in with Twitter, it comes in a problem.
The behavior: When done Sign in with Twitter, it redirect to /app. Then when /app is loaded for 20s like that then it go back to /auth/login again. This is keep repeating, non-stop until the browser hang.
Here is my code for Sign in with Twitter.
useAuth.js (same file with code above with loginWithTwitter)
const [operation, setOperation] = useState('login')
const loginWithTwitter = () => {
setOperation(type)
let provider = getTwitterProvider()
return firebase.auth().signInWithRedirect(provider)
}
const getTwitterRedirectResult = () => {
return firebase
.auth()
.getRedirectResult()
.then((result) => {
console.log(result)
var credential = result.credential;
var token = credential.accessToken;
var secret = credential.secret;
var twitterHandle = result.additionalUserInfo.username
if (operation === 'sign-up') {
// if sign up, here save to my db
createUserInDb(twitterHandle, token, secret).then(res=> {
setUser(res.data)
}).catch(error => setUser(null))
}
if (operation === 'login') {
// here get back the user details same as above
getUser()
}
}).catch((error) => {
console.log(error.message)
setErrorMessage(error.message)
setUser(null)
});
}
Then in my /auth/login and /auth/sign-up I have this code:
const Login = () => {
const { user, getTwitterRedirectResult } = useAuth() //
useEffect(() => {
getTwitterRedirectResult() // here call to twitter redirect result
}, [])
useEffect(() => {
if (user) {
// code redirect to app
router.push('/app')
}
})
}
So now, when login/sign up with password, is no problem. Once login, go to /app. then stay there.
But when sign in with Twitter, it go to /app. Stay there for 20s, then it redirect back to /auth/login. Basically is infinite loop.
So now my question:
What is the correct way to call
getTwitterRedirectin react? Is it call atuseEffect()when the page load?How to solve the infinite loop? Done login go to
/app, then it go back to/auth/loginagain.How to save user data to my own db when getting the result back from
getTwitterRedirect. So when Sign up I need to create the record, but when login with Twitter, I just need to get back the same record. But right now, it only have 1 functiongetTwitterRedirect, login and sign up also use this. So how can I solve this?
Please someone tell me what I doing wrong, I have totally no clue.
Thanks in advance.