英文:
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 "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
}
}, [])
// console.log(session.user.name)
return { session, loading , role ,name}
}
My comp:
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 />
</>
)
}
</>
)
> AFTER ADD useContext
Now i add authProvider.js with useContext :
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("Success logout");
} else {
console.error("Failed to logout");
}
} catch (error) {
console.error(error);
}
};
const authContextValue = {
authenticated,
login,
logout,
};
return (
<AuthContext.Provider value={authContextValue}>{children}</AuthContext.Provider>
);
}
And i have error :
Cannot destructure property 'authenticated' of '(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)' as it is undefined.
TypeError: Cannot destructure property 'authenticated' of '(0 , _services_authProvider__WEBPACK_IMPORTED_MODULE_14__.useAuth)(...)' as it is undefined.
Updating comp after 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>
</>
)
}
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论