Firebase onAuthStateChanged currentUser always null when first load a page React

Viewed 348

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:

  1. What is the correct way to call getTwitterRedirect in react? Is it call at useEffect() when the page load?

  2. How to solve the infinite loop? Done login go to /app, then it go back to /auth/login again.

  3. 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 function getTwitterRedirect, 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.

0 Answers
Related