Home > other >  Unable to prevent flashing unauthorized content in next.js before redirecting to a route
Unable to prevent flashing unauthorized content in next.js before redirecting to a route

Time:06-21

import JoinComponent from '@/components/join/JoinComponent'
import Footer from '@/components/Layouts/Footer'
import GuestLayout from '@/components/Layouts/GuestLayout'
import Navbar from '@/components/Layouts/Navbar'
import { useAuth } from '@/hooks/auth'
import { useRouter } from 'next/router'

const Join = () => {
    const router = useRouter()
    const { user } = useAuth({
        middleware: 'guest',
        redirectIfAuthenticated: '/',
    })

    if (user !== undefined) {
        return (
            <GuestLayout>
                <title>Join</title>
                <div></div>
            </GuestLayout>
        )
    } else {
        return (
            <GuestLayout>
                <title>Join</title>
                <Navbar />
                <JoinComponent />
                <Footer />{' '}
            </GuestLayout>
        )
    }
}

export default Join

It is supposed to conditionally render the layouts if the user is authenticated but it still renders the else part for a brief amount of time and then redirects to '/'.

I am unable to figure out why this is the case.

CodePudding user response:

import JoinComponent from '@/components/join/JoinComponent'
import Footer from '@/components/Layouts/Footer'
import Navbar from '@/components/Layouts/Navbar'
import Loader from '@/components/Loader'
import { useAuth } from '@/hooks/auth'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

const Join = () => {
    const [loading, setLoading] = useState(true)
    const { user } = useAuth({
        middleware: 'guest',
        redirectIfAuthenticated: '/',
    })

    useEffect(() => {
        console.log(user)
        if (user) {
            setLoading(true)
        }

        let t
        if (user === undefined) {
            t = setInterval(() => {
                setLoading(false)
            }, 2000)
        }

        return () => {
            clearInterval(t)
        }
    }, [user])

    return (
        <div>
            <title>Join</title>
            <Navbar />
            {loading ? <Loader /> : <JoinComponent />}
            <Footer />{' '}
        </div>
    )
}

export default Join

Although my code have changed significantly over time but I have solved the issue in this manner.

What is important to note that for a certain time the useAuth hook doesn't return a user instance and in that period the user remains undefined.

Later if the user is already authenticated a user object is returned, otherwise user remains undefined.

In this case, it is difficult to know immediately if the user object will be defined, therefore we have to wait for some time before setting the loading state to false.

In this way a sudden flash of the undesired component can be prevented and instead a loader can be rendered. However, the problem may arise in the future if the useAuth hook takes more time to return a user object than the hard coded time, that calls for another approach to this problem.

  • Related