next.js 在useEffect内部,刷新页面时触发了两个条件分支

xam8gpfp  于 2023-06-22  发布在  其他
关注(0)|答案(2)|浏览(173)

React组件中的useEffect代码。

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])

它使用一个数据库来管理auth(会话)。
刷新页面时有一个很大的问题,(登录,注销通过路由器重定向没有任何问题,只有当刷新页面时。),两个分支都会到达,所以在js控制台中,我们可以看到来自两个条件分支的日志。
'stay in page'goto login/goto login done
我认为这是由于session在刷新后发生了变化。第一次未定义,以触发第二个分支router.push,当会话被发现时,立即触发第一个分支stay in page
有没有什么建议可以绕过它?或者在React/NextJS中处理页面刷新**的好方法?以前有没有人遇到过类似或相同的问题?

lb3vh1jj

lb3vh1jj1#

在代码中,每当session或路由器的值发生变化时(useEffect的第二个参数)都会执行useEffect。因此,if和else并没有在useEffect的同一次运行中执行,尽管是在两次不同的运行中执行的,这两次运行可能是快速连续执行的。
这里有一个方法可以实现你所追求的。
1.使用useState创建和管理变量的状态
1.在useEffect中,通过应用逻辑检查会话来设置状态(或不设置状态)
1.在返回中呈现当前页面或显示登录页面。
示例实现:

const App = (props) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  
  useEffect(()=>{
    //apply the logic and set the state
    if(logic) setIsLoggedIn(true);
  },[]) 
  
  return  {isLoggedIn ? <ActiveApp /> : <Login />}

}
af7jpaap

af7jpaap2#

我终于找到了根本原因。
它来自于supabase auth helper的useSession钩子,它是一个异步函数,它不包括正在加载或错误的状态,这意味着它在开始时总是空的(这意味着它正在加载)。
解决这个问题的简单方法,是直接使用useSessionContextsession仍将以异步方式获得,但isLoadingerror状态可以以同步方式获得以解决此问题,并且它们可以用于useEffect内部的条件分支。
新代码将是这样的:

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])

相关问题