哪个钩子更适合用于授权验证?

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

Which hook is more suitable for authorization verification?

问题

我在思考从逻辑角度来看,哪种方法会是最正确的。我想检查渲染组件的授权,但现在 useEffect 只在页面首次渲染或重新启动时起作用,因为它有一个依赖项 [ ]。哪种实现方式会是最简洁的,更重要的是从 hooks 的角度来看,以便用户在授权后获取组件而无需重新启动。

我有一个名为 auth 的函数:

import { useEffect, useState } from "react"

export function useCheckCookieToken() {
  const [session, setSession] = useState()
  const [loading, setLoading] = useState(true)
  const [name, setName] = useState('')
  const [role, setRole] = useState('')

  useEffect(() => {
    let cancel = false
    async function sessionPost() {
      const res = await fetch(`/api/checkCookie`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        },
      })
      if (res.ok) {
        const result = await res.json()
        if (!cancel) {
          setSession(result)
          setName(result.user.name)
          setRole(result.user.role)
          setLoading(false)
        }
      } else {
        setLoading(false)
      }
    }
    sessionPost()
    return () => {
      cancel = true
    }
  }, [])

  return { session, loading, role, name }
}

我的组件:

const [authenticated, setAuthenticated] = useState(false)

const { session, loading, name } = useCheckCookieToken()

useEffect(() => {
  if (session) {
    setNameUser(name)
    setAuthenticated(true)
  } else {
    setAuthenticated(false)
  }
}, [session])

return (
  <>
    {
      loading ? (
        <div><CircularProgress/></div>
      ) : session ? (
        <>
          <Auth />
        </>
      ) : (
        <>
          <NotAuth />
        </>
      )
    }
  </>
)

添加 useContext 后

现在我添加了带有 useContext 的 authProvider.js

import { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export function useAuth() {
    return useContext(AuthContext);
}

export function AuthProvider({ children }) {
    const [authenticated, setAuthenticated] = useState(false);
    const [session, setSession] = useState(null)
    const [loading, setLoading] = useState(true)
    const [name, setName] = useState('')
    const [role, setRole] = useState('')

    const login = async () => {
        try {
            const res = await fetch(`/api/checkCookie`, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json'
                },
            });
            if (res.ok) {
                const result = await res.json();
                setSession(result);
                setName(result.user.name);
                setRole(result.user.role);
                setLoading(false);
                setAuthenticated(true);
            } else {
                setLoading(false);
                setAuthenticated(false);
            }
        } catch (error) {
            console.error(error);
            setLoading(false);
            setAuthenticated(false);
        }
    };

    const logout = async () => {
        try {
            const res = await fetch('/api/logout', {
                method: 'GET',
                headers: {
                    'Authorization': 'bearer ' + localStorage.getItem('sid'),
                    'Content-Type': 'application/json'
                }
            });
            if (res.ok) {
                setAuthenticated(false);
                console.log("成功退出登录");
            } else {
                console.error("退出登录失败");
            }
        } catch (error) {
            console.error(error);
        }
    };


    const authContextValue = {
        authenticated,
        login,
        logout,
    };

    return (
        <AuthContext.Provider value={authContextValue}>{children}</AuthContext.Provider>
    );
}   

但我遇到了一个错误:

无法解构属性 'authenticated' of '(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)',因为它是未定义的。
TypeError: Cannot destructure property 'authenticated' of '(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)' as it is undefined.

使用 useContext 更新后的组件:

function MainPage() {
  const { authenticated, login, logout } = useAuth();

 useEffect(() => {
    if (authenticated) {
      setNameUser(name);
    } else {
      setNameUser('');
    }
  }, [authenticated]);

return (
    <>
      <AuthProvider.Provider value={{name}}>
        {
          loading ? (
            <div><CircularProgress /></div> 
          ) : session ? (
            <>
            <h1>{name}</h1>
             
            </>
          ) : (
            <>
              <Bar/>
            </>
          )
        }
      </AuthProvider.Provider>
    </>
  )
}
英文:

I'm wondering how the method will be the most correct from the point of view of logic. I want to check authorization for rendering components , but now useEffect only works there when the page is first rendered or restarted , because it has a dependency [ ] . Which implementation will be the most loconic, and most importantly correct from the point of view of hooks, so that the user receives components after authorization without restarting.

I have function auth :

 import { useEffect, useState } from &quot;react&quot;
export function useCheckCookieToken() {
const [session, setSession] = useState()
const [loading, setLoading] = useState(true)
const [name,setName]=useState(&#39;&#39;)
const [role,setRole]=useState(&#39;&#39;)
useEffect(() =&gt; {
let cancel = false
async function sessionPost() {
const res = await fetch(`/api/checkCookie`, {
method: &#39;GET&#39;,
headers: {
&#39;Content-Type&#39;: &#39;application/json&#39;
},
})
if (res.ok) {
const result = await res.json()
if (!cancel) {
setSession(result)
setName(result.user.name)
setRole(result.user.role)
setLoading(false)
}
} else {
setLoading(false)
}
}
sessionPost()
return () =&gt; {
cancel = true
}
}, [])
//  console.log(session.user.name)
return { session, loading , role ,name}
}

My comp:

const [authenticated, setAuthenticated] = useState(false); 
const { session, loading, name } = useCheckCookieToken();
useEffect(() =&gt; {
if (session) {
setNameUser(name);
setAuthenticated(true);
} else {
setAuthenticated(false);
}
}, [session]);
return (
&lt;&gt;
{
loading ? (
&lt;div&gt;&lt;CircularProgress/&gt;&lt;/div&gt; 
) : session ? (
&lt;&gt;
&lt;Auth /&gt;
/&gt;
&lt;/&gt;
) : (
&lt;&gt;
&lt;NotAuth /&gt;
&lt;/&gt;
)
}
&lt;/&gt;
)

> AFTER ADD useContext

Now i add authProvider.js with useContext :

import { createContext, useContext, useState } from &#39;react&#39;;
const AuthContext = createContext();
export function useAuth() {
return useContext(AuthContext);
}
export function AuthProvider({ children }) {
const [authenticated, setAuthenticated] = useState(false);
const [session, setSession] = useState(null)
const [loading, setLoading] = useState(true)
const [name, setName] = useState(&#39;&#39;)
const [role, setRole] = useState(&#39;&#39;)
const login = async () =&gt; {
try {
const res = await fetch(`/api/checkCookie`, {
method: &#39;GET&#39;,
headers: {
&#39;Content-Type&#39;: &#39;application/json&#39;
},
});
if (res.ok) {
const result = await res.json();
setSession(result);
setName(result.user.name);
setRole(result.user.role);
setLoading(false);
setAuthenticated(true);
} else {
setLoading(false);
setAuthenticated(false);
}
} catch (error) {
console.error(error);
setLoading(false);
setAuthenticated(false);
}
};
const logout = async () =&gt; {
try {
const res = await fetch(&#39;/api/logout&#39;, {
method: &#39;GET&#39;,
headers: {
&#39;Authorization&#39;: &#39;bearer &#39; + localStorage.getItem(&#39;sid&#39;),
&#39;Content-Type&#39;: &#39;application/json&#39;
}
});
if (res.ok) {
setAuthenticated(false);
console.log(&quot;Success logout&quot;);
} else {
console.error(&quot;Failed to logout&quot;);
}
} catch (error) {
console.error(error);
}
};
const authContextValue = {
authenticated,
login,
logout,
};
return (
&lt;AuthContext.Provider value={authContextValue}&gt;{children}&lt;/AuthContext.Provider&gt;
);
}   

And i have error :

Cannot destructure property &#39;authenticated&#39; of &#39;(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)&#39; as it is undefined.
TypeError: Cannot destructure property &#39;authenticated&#39; of &#39;(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)&#39; as it is undefined.

Updating comp after useContext:

function MainPage() {
const { authenticated, login, logout } = useAuth();
useEffect(() =&gt; {
if (authenticated) {
setNameUser(name);
} else {
setNameUser(&#39;&#39;);
}
}, [authenticated]);
return (
&lt;&gt;
&lt;AuthProvider.Provider value={{name}}&gt;
{
loading ? (
&lt;div&gt;&lt;CircularProgress /&gt;&lt;/div&gt; 
) : session ? (
&lt;&gt;
&lt;h1&gt;{name}&lt;/h1&gt;
&lt;/&gt;
) : (
&lt;&gt;
&lt;Bar/&gt;
&lt;/&gt;
)
}
&lt;/AuthProvider.Provider&gt;
&lt;/&gt;
)
}

答案1

得分: 1

最好的方法是使用useContext Hook。您需要全局访问用户状态。

您可以查看如何实现这一点的链接:
点击此处查看链接描述

英文:

the best way is to use useContext Hook. u need to access the users state globally.

you can see how to implement this from link below:
enter link description here

huangapple
  • 本文由 发表于 2023年6月1日 15:26:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379568.html
匿名

发表评论

匿名网友

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

确定