Inside useEffect, two conditional branches are triggered when the page is refreshed
P粉798343415
2023-09-03 14:09:00
<p>This is the <code>useEffect</code> code in the React component. </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>It uses supabase to manage authentication (session). </p>
<p>There is a very strange problem when refreshing the page (there is no problem at all with login and logout redirection through the router, it only appears when the page is refreshed.), both branches will be reached, so in the js console, we can see Log conditional branch from two branches. </p>
<p><code>"Stay on page"</code> and <code>Go to login</code>/<code>Go to login complete</code>. </p>
<blockquote>
<p>I think this is due to the <code>session</code> changing after the refresh. The first time it is undefined, the second branch <code>router.push</code> is triggered. When the session is found, the first branch <code>stays on the page</code> is triggered immediately. </p>
</blockquote>
<p>Any suggestions on how to get around it? Or are there any <strong>good practices</strong> for handling page refreshes in React/NextJS? Or has anyone encountered similar or the same problem before? </p>
In your code, useEffect will be executed whenever the value of the session or router changes (the second parameter of useEffect). Therefore, neither if nor else are executed in the same run of useEffect, although they are executed in two different runs that may be executed in rapid succession.
This is one way to achieve what you are after.
Example implementation:
Finally, I found the root cause.
It comes from the supabase auth helper, it is an async function, it does not contain the status of whether it is loading or wrong, which means it is at the beginning (which means it is loading).
The simple way to solve this problem is to use directly
The new code will look like this:useSessionContext
.session
will still be fetched asynchronously, but theisLoading
anderror
statuses can be fetched synchronously to resolve this issue, and they can be used withuseEffect# Conditional branches within ##.