skip to Main Content

This is the useEffect code in the React component.

  import { useSession } from '@supabase/auth-helpers-react'
  const session = useSession()
  useEffect(() => {
    if (session) {
      console.debug('stay in page')
    } else {
      console.debug('goto login')
      router.push('/login').then(
        () => {
          console.debug('goto login done')
        }
      )
    }
  }, [session, router])

It uses a supabase to manage auth (session).

It has a very weid issue when refresh page, (login, logout redirect through router has no issues at all, only when Refresh page.), both branches will be reached, so in js console, we could see logs from both condition branches.

'stay in page' and goto login/ goto login done.

I assume it is due to session changed after refresh. 1st time is undefined, to trigger the 2nd brach router.push, immediately, when session be found, triggers the 1st branch stay in page.

Is there any suggestion to bypass it? Or any good practice to handle page refresh in React/NextJS? Or anyone has similar or the same issue before?

2

Answers


  1. Chosen as BEST ANSWER

    Finally, I got the root cause for this.

    It is from the useSession hook from supabase auth helper, it is an async function, and it does not include the state of whether it is loading or error, which it means it will always be null in the beginning (which it means it is under loading).

    The simple solution to solve it, is to use useSessionContext directly instead. session will still be gotten in an async way, but isLoading and error state can be gotten in a sync way to resolve this issue, and they can be used for condition branching inside useEffect.

    New code will be like this:

      import { useSessionContext } from '@supabase/auth-helpers-react'
      const {isLoading, session} = useSessionContext()
      useEffect(() => {
    
        if (isLoading) {
          console.debug('show loading page')
        }
        else if (session) {
          console.debug('stay in page')
        } 
        else {
          console.debug('goto login')
          router.push('/login').then(
            () => {
              console.debug('goto login done')
            }
          )
        }
      }, [session, isLoading, router])
    
    

  2. In your code, useEffect will be executed whenever value for session or router changes (the 2nd parameter to useEffect). Hence, both if and else are not being executed in the same run of useEffect, albeit, in two different runs that are executed perhaps in quick succession.

    Here is one way of achieving what you are after.

    1. Create and manage the state of a variable using useState
    2. In the useEffect, set the state (or not) by applying logic to check session
    3. In the return either render the current page or show the login page.

    A sample implementation:

    const App = (props) => {
      const [isLoggedIn, setIsLoggedIn] = useState(false);
      
      useEffect(()=>{
        //apply the logic and set the state
        if(logic) setIsLoggedIn(true);
      },[]) 
      
      return  {isLoggedIn ? <ActiveApp /> : <Login />}
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search