Return is executed before getting session in react using Supabase

huangapple go评论57阅读模式
英文:

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 &#39;react&#39;
import &#39;./App.css&#39;
import {Navigate} from &#39;react-router-dom&#39;
import { supabase } from &#39;./helpers/supabaseClient&#39;

function App() {
  const [session, setSession] = useState(null)

  useEffect(() =&gt; {
    supabase.auth.getSession().then(({ data: { session } }) =&gt; {
      setSession(session)
    })

    supabase.auth.onAuthStateChange((_event, session) =&gt; {
      setSession(session)
    })
    
    console.log(session);
  }, [])
  

  return (
    &lt;div className=&quot;&quot;&gt;
      {session ? &lt;Navigate to=&quot;/home&quot;&gt;&lt;/Navigate&gt; : &lt;Navigate to=&quot;/account&quot;&gt;&lt;/Navigate&gt;}
      {/* {true ? &lt;Navigate to=&quot;/home&quot;&gt;&lt;/Navigate&gt; : &lt;Navigate to=&quot;/account&quot;&gt;&lt;/Navigate&gt;} */}
    &lt;/div&gt;
  )
}

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(() =&gt; {
    supabase.auth.getSession()
      .then(({ data: { session } }) =&gt; {
        setSession(session);
      })
      .finally(() =&gt; {
        setIsLoading(false);
      });

    supabase.auth.onAuthStateChange((_event, session) =&gt; {
      setSession(session);
    });
  }, []);
  
  if (isLoading) {
    return null; // or loading indicator/spinner/etc
  }

  return (
    &lt;div className=&quot;&quot;&gt;
      &lt;Navigate to={session.access_token ? &quot;/home&quot; : &quot;/account&quot;} replace /&gt;
    &lt;/div&gt;
  );
}

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(); // &lt;-- initially undefined

  useEffect(() =&gt; {
    supabase.auth.getSession()
      .then(({ data: { session } }) =&gt; {
        setSession(session); // &lt;-- set either null/user object
      });

    supabase.auth.onAuthStateChange((_event, session) =&gt; {
      setSession(session); // &lt;-- set either null/user object
    });
  }, []);
  
  if (session === undefined) {
    return null; // or loading indicator/spinner/etc
  }

  return (
    &lt;div className=&quot;&quot;&gt;
      &lt;Navigate to={session.access_token ? &quot;/home&quot; : &quot;/account&quot;} replace /&gt;
    &lt;/div&gt;
  );
}

答案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() 函数内。

编辑:你必须使用 &quot;===&quot; 并比较 session === null 和 session === undefined,而不是 session.access_token == null 和 session == null。
英文:

Solved it!

I just changed

{session ? &lt;Navigate to=&quot;/home&quot;&gt;&lt;/Navigate&gt; : &lt;Navigate to=&quot;/account&quot;&gt;&lt;/Navigate&gt;}

to

{session==null?&lt;&gt;&lt;/&gt;:(session.access_token==null ?&lt;Navigate to=&quot;/account&quot;&gt;&lt;/Navigate&gt; :&lt;Navigate to=&quot;/home&quot;&gt;&lt;/Navigate&gt;  )}

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

huangapple
  • 本文由 发表于 2023年4月4日 15:47:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75926764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定