如何正确使用Asgardeo的getAccessToken避免React组件无限重渲染?
Asgardeo React组件获取Access Token的无限重渲染问题
我在React应用中使用Asgardeo认证功能,希望在组件中获取access token,但在useEffect中调用getAccessToken()时,组件出现无限重渲染问题。以下是我的代码:
import { useAsgardeo } from '@asgardeo/react'; const Component = () => { const { getAccessToken } = useAsgardeo(); useEffect(() => { getAccessToken() .then((tk) => { const response = fetch("http://localhost:3000/api", { method: "GET", headers: { Authorization: `Bearer ${tk}`, }, }); console.log("Volunteer Dashboard - Fetched user data:", response); }); }, []);
疑问:
- 如何正确使用Asgardeo的
getAccessToken()hook获取access token? - 是否需要将
getAccessToken加入useEffect的dependency array? - 如何确保仅在用户登录后获取一次access token?
当前使用的是@asgardeo/react包。
解答
1. 正确使用getAccessToken()的方式
getAccessToken()是异步方法,调用后返回Promise,需放在useEffect或事件回调中执行,不能直接在组件渲染阶段调用。另外,你的代码中fetch也是异步操作,需要用await或额外的.then()处理,否则console.log拿到的是Promise对象而非实际响应数据:
useEffect(() => { const fetchData = async () => { try { const token = await getAccessToken(); const response = await fetch("http://localhost:3000/api", { method: "GET", headers: { Authorization: `Bearer ${token}`, }, }); const data = await response.json(); // 解析响应数据 console.log("Volunteer Dashboard - Fetched user data:", data); } catch (err) { console.error("获取token或请求API失败:", err); } }; fetchData(); }, [getAccessToken]);
2. 是否要将getAccessToken加入useEffect依赖数组?
必须加入。ESLint的react-hooks/exhaustive-deps规则会提示该问题,因为getAccessToken是从useAsgardeo返回的方法,其引用可能在组件重渲染时变化。若不加入,可能引发闭包问题;若直接加入后因方法引用频繁变化导致useEffect重复执行,可通过useRef缓存方法解决:
const { getAccessToken } = useAsgardeo(); const getAccessTokenRef = useRef(getAccessToken); // 实时更新缓存的方法引用 useEffect(() => { getAccessTokenRef.current = getAccessToken; }, [getAccessToken]); useEffect(() => { const fetchData = async () => { try { const token = await getAccessTokenRef.current(); // ... 后续请求逻辑 } catch (err) { console.error("请求失败:", err); } }; fetchData(); }, []); // 此处无需加入getAccessToken,已通过ref缓存
3. 确保仅在用户登录后获取一次token
useAsgardeo提供了isAuthenticated状态,可用来判断用户登录状态,结合该状态触发useEffect,就能保证仅在登录后执行一次:
import { useAsgardeo } from '@asgardeo/react'; const Component = () => { const { getAccessToken, isAuthenticated } = useAsgardeo(); const [hasFetchedToken, setHasFetchedToken] = useState(false); useEffect(() => { // 未登录或已获取过token时直接返回 if (!isAuthenticated || hasFetchedToken) return; const fetchData = async () => { try { const token = await getAccessToken(); const response = await fetch("http://localhost:3000/api", { method: "GET", headers: { Authorization: `Bearer ${token}`, }, }); const data = await response.json(); console.log("Volunteer Dashboard - Fetched user data:", data); setHasFetchedToken(true); // 标记已获取过token,避免重复执行 } catch (err) { console.error("请求失败:", err); } }; fetchData(); }, [getAccessToken, isAuthenticated, hasFetchedToken]);
通过isAuthenticated判断登录状态,再用hasFetchedToken标记是否已执行过请求,就能彻底避免无限重渲染,确保仅在用户登录后获取一次token并请求数据。
内容的提问来源于stack exchange,提问作者TharkaUJ
相关产品推荐
相关产品推荐

