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

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

Which hook is more suitable for authorization verification?

问题

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

我有一个名为 auth 的函数:

  1. import { useEffect, useState } from "react"
  2. export function useCheckCookieToken() {
  3. const [session, setSession] = useState()
  4. const [loading, setLoading] = useState(true)
  5. const [name, setName] = useState('')
  6. const [role, setRole] = useState('')
  7. useEffect(() => {
  8. let cancel = false
  9. async function sessionPost() {
  10. const res = await fetch(`/api/checkCookie`, {
  11. method: 'GET',
  12. headers: {
  13. 'Content-Type': 'application/json'
  14. },
  15. })
  16. if (res.ok) {
  17. const result = await res.json()
  18. if (!cancel) {
  19. setSession(result)
  20. setName(result.user.name)
  21. setRole(result.user.role)
  22. setLoading(false)
  23. }
  24. } else {
  25. setLoading(false)
  26. }
  27. }
  28. sessionPost()
  29. return () => {
  30. cancel = true
  31. }
  32. }, [])
  33. return { session, loading, role, name }
  34. }

我的组件:

  1. const [authenticated, setAuthenticated] = useState(false)
  2. const { session, loading, name } = useCheckCookieToken()
  3. useEffect(() => {
  4. if (session) {
  5. setNameUser(name)
  6. setAuthenticated(true)
  7. } else {
  8. setAuthenticated(false)
  9. }
  10. }, [session])
  11. return (
  12. <>
  13. {
  14. loading ? (
  15. <div><CircularProgress/></div>
  16. ) : session ? (
  17. <>
  18. <Auth />
  19. </>
  20. ) : (
  21. <>
  22. <NotAuth />
  23. </>
  24. )
  25. }
  26. </>
  27. )

添加 useContext 后

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

  1. import { createContext, useContext, useState } from 'react';
  2. const AuthContext = createContext();
  3. export function useAuth() {
  4. return useContext(AuthContext);
  5. }
  6. export function AuthProvider({ children }) {
  7. const [authenticated, setAuthenticated] = useState(false);
  8. const [session, setSession] = useState(null)
  9. const [loading, setLoading] = useState(true)
  10. const [name, setName] = useState('')
  11. const [role, setRole] = useState('')
  12. const login = async () => {
  13. try {
  14. const res = await fetch(`/api/checkCookie`, {
  15. method: 'GET',
  16. headers: {
  17. 'Content-Type': 'application/json'
  18. },
  19. });
  20. if (res.ok) {
  21. const result = await res.json();
  22. setSession(result);
  23. setName(result.user.name);
  24. setRole(result.user.role);
  25. setLoading(false);
  26. setAuthenticated(true);
  27. } else {
  28. setLoading(false);
  29. setAuthenticated(false);
  30. }
  31. } catch (error) {
  32. console.error(error);
  33. setLoading(false);
  34. setAuthenticated(false);
  35. }
  36. };
  37. const logout = async () => {
  38. try {
  39. const res = await fetch('/api/logout', {
  40. method: 'GET',
  41. headers: {
  42. 'Authorization': 'bearer ' + localStorage.getItem('sid'),
  43. 'Content-Type': 'application/json'
  44. }
  45. });
  46. if (res.ok) {
  47. setAuthenticated(false);
  48. console.log("成功退出登录");
  49. } else {
  50. console.error("退出登录失败");
  51. }
  52. } catch (error) {
  53. console.error(error);
  54. }
  55. };
  56. const authContextValue = {
  57. authenticated,
  58. login,
  59. logout,
  60. };
  61. return (
  62. <AuthContext.Provider value={authContextValue}>{children}</AuthContext.Provider>
  63. );
  64. }

但我遇到了一个错误:

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

使用 useContext 更新后的组件:

  1. function MainPage() {
  2. const { authenticated, login, logout } = useAuth();
  3. useEffect(() => {
  4. if (authenticated) {
  5. setNameUser(name);
  6. } else {
  7. setNameUser('');
  8. }
  9. }, [authenticated]);
  10. return (
  11. <>
  12. <AuthProvider.Provider value={{name}}>
  13. {
  14. loading ? (
  15. <div><CircularProgress /></div>
  16. ) : session ? (
  17. <>
  18. <h1>{name}</h1>
  19. </>
  20. ) : (
  21. <>
  22. <Bar/>
  23. </>
  24. )
  25. }
  26. </AuthProvider.Provider>
  27. </>
  28. )
  29. }
英文:

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 :

  1. import { useEffect, useState } from &quot;react&quot;
  2. export function useCheckCookieToken() {
  3. const [session, setSession] = useState()
  4. const [loading, setLoading] = useState(true)
  5. const [name,setName]=useState(&#39;&#39;)
  6. const [role,setRole]=useState(&#39;&#39;)
  7. useEffect(() =&gt; {
  8. let cancel = false
  9. async function sessionPost() {
  10. const res = await fetch(`/api/checkCookie`, {
  11. method: &#39;GET&#39;,
  12. headers: {
  13. &#39;Content-Type&#39;: &#39;application/json&#39;
  14. },
  15. })
  16. if (res.ok) {
  17. const result = await res.json()
  18. if (!cancel) {
  19. setSession(result)
  20. setName(result.user.name)
  21. setRole(result.user.role)
  22. setLoading(false)
  23. }
  24. } else {
  25. setLoading(false)
  26. }
  27. }
  28. sessionPost()
  29. return () =&gt; {
  30. cancel = true
  31. }
  32. }, [])
  33. // console.log(session.user.name)
  34. return { session, loading , role ,name}
  35. }

My comp:

  1. const [authenticated, setAuthenticated] = useState(false);
  2. const { session, loading, name } = useCheckCookieToken();
  3. useEffect(() =&gt; {
  4. if (session) {
  5. setNameUser(name);
  6. setAuthenticated(true);
  7. } else {
  8. setAuthenticated(false);
  9. }
  10. }, [session]);
  11. return (
  12. &lt;&gt;
  13. {
  14. loading ? (
  15. &lt;div&gt;&lt;CircularProgress/&gt;&lt;/div&gt;
  16. ) : session ? (
  17. &lt;&gt;
  18. &lt;Auth /&gt;
  19. /&gt;
  20. &lt;/&gt;
  21. ) : (
  22. &lt;&gt;
  23. &lt;NotAuth /&gt;
  24. &lt;/&gt;
  25. )
  26. }
  27. &lt;/&gt;
  28. )

> AFTER ADD useContext

Now i add authProvider.js with useContext :

  1. import { createContext, useContext, useState } from &#39;react&#39;;
  2. const AuthContext = createContext();
  3. export function useAuth() {
  4. return useContext(AuthContext);
  5. }
  6. export function AuthProvider({ children }) {
  7. const [authenticated, setAuthenticated] = useState(false);
  8. const [session, setSession] = useState(null)
  9. const [loading, setLoading] = useState(true)
  10. const [name, setName] = useState(&#39;&#39;)
  11. const [role, setRole] = useState(&#39;&#39;)
  12. const login = async () =&gt; {
  13. try {
  14. const res = await fetch(`/api/checkCookie`, {
  15. method: &#39;GET&#39;,
  16. headers: {
  17. &#39;Content-Type&#39;: &#39;application/json&#39;
  18. },
  19. });
  20. if (res.ok) {
  21. const result = await res.json();
  22. setSession(result);
  23. setName(result.user.name);
  24. setRole(result.user.role);
  25. setLoading(false);
  26. setAuthenticated(true);
  27. } else {
  28. setLoading(false);
  29. setAuthenticated(false);
  30. }
  31. } catch (error) {
  32. console.error(error);
  33. setLoading(false);
  34. setAuthenticated(false);
  35. }
  36. };
  37. const logout = async () =&gt; {
  38. try {
  39. const res = await fetch(&#39;/api/logout&#39;, {
  40. method: &#39;GET&#39;,
  41. headers: {
  42. &#39;Authorization&#39;: &#39;bearer &#39; + localStorage.getItem(&#39;sid&#39;),
  43. &#39;Content-Type&#39;: &#39;application/json&#39;
  44. }
  45. });
  46. if (res.ok) {
  47. setAuthenticated(false);
  48. console.log(&quot;Success logout&quot;);
  49. } else {
  50. console.error(&quot;Failed to logout&quot;);
  51. }
  52. } catch (error) {
  53. console.error(error);
  54. }
  55. };
  56. const authContextValue = {
  57. authenticated,
  58. login,
  59. logout,
  60. };
  61. return (
  62. &lt;AuthContext.Provider value={authContextValue}&gt;{children}&lt;/AuthContext.Provider&gt;
  63. );
  64. }

And i have error :

  1. Cannot destructure property &#39;authenticated&#39; of &#39;(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)&#39; as it is undefined.
  2. 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:

  1. function MainPage() {
  2. const { authenticated, login, logout } = useAuth();
  3. useEffect(() =&gt; {
  4. if (authenticated) {
  5. setNameUser(name);
  6. } else {
  7. setNameUser(&#39;&#39;);
  8. }
  9. }, [authenticated]);
  10. return (
  11. &lt;&gt;
  12. &lt;AuthProvider.Provider value={{name}}&gt;
  13. {
  14. loading ? (
  15. &lt;div&gt;&lt;CircularProgress /&gt;&lt;/div&gt;
  16. ) : session ? (
  17. &lt;&gt;
  18. &lt;h1&gt;{name}&lt;/h1&gt;
  19. &lt;/&gt;
  20. ) : (
  21. &lt;&gt;
  22. &lt;Bar/&gt;
  23. &lt;/&gt;
  24. )
  25. }
  26. &lt;/AuthProvider.Provider&gt;
  27. &lt;/&gt;
  28. )
  29. }

答案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:

确定