搜尋

首頁  >  問答  >  主體

在 useEffect 內部,刷新頁面時會觸發兩個條件分支

<p>這是React元件中的<code>useEffect</code>代碼。 </p> <pre class="brush:js;toolbar:false;"> 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]) </pre> <p>它使用supabase來管理身份驗證(會話)。 </p> <p>刷新頁面時有一個非常奇怪的問題(透過路由器登入、登出重定向完全沒有問題,只有在刷新頁面時才出現。),兩個分支都會到達,所以在js控制台中,我們可以看到來自兩個分支的日誌條件分支。 </p> <p><code>「留在頁面」</code> 和<code>前往登入</code>/<code>前往登入完成</code>。 </p> <blockquote> <p>我認為這是由於刷新後<code>會話</code>發生了變化。第一次未定義,觸發第二個分支<code>router.push</code>,當找到會話時,立即觸發第一個分支<code>停留在頁面</code>。 </p> </blockquote> <p>有什麼建議可以繞過它嗎?或在 React/NextJS 中有任何<strong>處理頁面刷新的良好實踐</strong>?或者有人以前遇到過類似或相同的問題嗎? </p>
P粉798343415P粉798343415437 天前631

全部回覆(2)我來回復

  • P粉276876663

    P粉2768766632023-09-04 12:40:54

    在您的程式碼中,只要會話或路由器的值發生變更(useEffect 的第二個參數),就會執行 useEffect。因此,if 和 else 都不會在 useEffect 的同一次運行中執行,儘管是在可能快速連續執行的兩次不同運行中執行。

    這是實現您所追求的目標的一種方法。

    1. 使用 useState 建立和管理變數的狀態
    2. 在 useEffect 中,透過套用邏輯檢查會話來設定(或不設定)狀態
    3. 在回傳中呈現目前頁面或顯示登入頁面。

    範例實作:

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

    回覆
    0
  • P粉035600555

    P粉0356005552023-09-04 00:28:17

    終於,我找到了根本原因。

    它來自 supabase auth helper,它是一個非同步函數,它不包含是否正在載入或錯誤的狀態,這表示它在開始(這表示它正在載入)。

    解決這個問題的簡單方法是直接使用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])
    
    

    回覆
    0
  • 取消回覆