英文:
Return is executed before getting session in react using Supabase
问题
App.jsx文件
import { useEffect, useState } from 'react'
import './App.css'
import { Navigate } from 'react-router-dom'
import { supabase } from './helpers/supabaseClient'
function App() {
const [session, setSession] = useState(null)
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session)
})
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session)
})
console.log(session);
}, [])
return (
<div className="">
{session ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>}
{/* {true ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>} */}
</div>
)
}
export default App
在使用Navigate
函数之前,我希望以某种方式获取会话返回值。我尝试过使用await
函数,但似乎不起作用。我使用了setTimeout(2000)
,但也没有起作用。应该怎么做?我不希望将其变成单页应用程序。我希望以某种方式使用Navigate
。
英文:
I want to somehow get my return value after getting session.
App.jsx file
import { useEffect, useState } from 'react'
import './App.css'
import {Navigate} from 'react-router-dom'
import { supabase } from './helpers/supabaseClient'
function App() {
const [session, setSession] = useState(null)
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session)
})
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session)
})
console.log(session);
}, [])
return (
<div className="">
{session ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>}
{/* {true ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>} */}
</div>
)
}
export default App
The Navigate function routes to another react component before I am able to retrieve session using useEffect.
I have tried using await function but that too seems to not work. I used setTimeout(2000). But that didn't work either.
What should be done. I don't prefer to make it a single page application. I want to use Navigate somehow.
答案1
得分: 2
这个组件无论session
的值如何,都会渲染一个Navigate
组件。React组件渲染是完全同步的,因此在任何异步逻辑/副作用等完成之前,返回将始终发生。
我猜你想等到效果运行并填充session
状态后,才允许渲染任何一个Navigate
组件。使用加载状态,并在获取会话数据时有条件地提前返回。
示例:
function App() {
const [isLoading, setIsLoading] = useState(true);
const [session, setSession] = useState(null);
useEffect(() => {
supabase.auth.getSession()
.then(({ data: { session } }) => {
setSession(session);
})
.finally(() => {
setIsLoading(false);
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
}, []);
if (isLoading) {
return null; // 或加载指示器/旋转器等
}
return (
<div className="">
<Navigate to={session.access_token ? "/home" : "/account"} replace />
</div>
);
}
如果session
状态值对于未经授权的用户为null
,对于经过身份验证的用户为定义的对象,那么你可以使用单一状态来实现相同的效果。
示例:
function App() {
const [session, setSession] = useState(); // <-- 最初为undefined
useEffect(() => {
supabase.auth.getSession()
.then(({ data: { session } }) => {
setSession(session); // <-- 设置为null或用户对象
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session); // <-- 设置为null或用户对象
});
}, []);
if (session === undefined) {
return null; // 或加载指示器/旋转器等
}
return (
<div className="">
<Navigate to={session.access_token ? "/home" : "/account"} replace />
</div>
);
}
英文:
The component renders a Navigate
component regardless of any session
value. React component renders are completely synchronous, so a return will always happen prior to any asynchronous logic/side-effects/etc completing.
I'm guessing you want to wait until the effect runs and populates the session
state prior to allowing either of the Navigate
components to be rendered. Use a loading state and conditionally return early while the session data is fetched.
Example:
function App() {
const [isLoading, setIsLoading] = useState(true);
const [session, setSession] = useState(null);
useEffect(() => {
supabase.auth.getSession()
.then(({ data: { session } }) => {
setSession(session);
})
.finally(() => {
setIsLoading(false);
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
}, []);
if (isLoading) {
return null; // or loading indicator/spinner/etc
}
return (
<div className="">
<Navigate to={session.access_token ? "/home" : "/account"} replace />
</div>
);
}
If the session
state value is either null
for unauthorized users, and a defined object for authenticated users, then you can accomplish the same with the single state.
Example:
function App() {
const [session, setSession] = useState(); // <-- initially undefined
useEffect(() => {
supabase.auth.getSession()
.then(({ data: { session } }) => {
setSession(session); // <-- set either null/user object
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session); // <-- set either null/user object
});
}, []);
if (session === undefined) {
return null; // or loading indicator/spinner/etc
}
return (
<div className="">
<Navigate to={session.access_token ? "/home" : "/account"} replace />
</div>
);
}
答案2
得分: 0
解决了!
我只是将
{session ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>}
改成了
{session==null?<></>:(session.access_token==null ?<Navigate to="/account"></Navigate> :<Navigate to="/home"></Navigate> )}
在 return() 函数内。
编辑:你必须使用 "===" 并比较 session === null 和 session === undefined,而不是 session.access_token == null 和 session == null。
英文:
Solved it!
I just changed
{session ? <Navigate to="/home"></Navigate> : <Navigate to="/account"></Navigate>}
to
{session==null?<></>:(session.access_token==null ?<Navigate to="/account"></Navigate> :<Navigate to="/home"></Navigate> )}
Inside return()
Edit : you have to use "===" and compare between session === null and session === undefined rather than session.access_token == null and session == null respectively
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论