React Native中如何导出更新后变量?求AWS Cognito优化方案
一、导出变量更新后无法获取的问题修复
问题原因
你当前导出的default对象是模块加载时就创建的,里面的phoneNumber和username属性保存的是初始null值的快照。后续调用getLoggedinUser更新变量时,这个对象的属性不会同步更新——因为它们是独立的原始值引用,和后续修改的变量没有关联。
修复方案
这里提供两种简单可行的修改方式:
方案1:用统一对象存储用户数据
修改AuthUser.js,把用户数据存在一个对象里,这样所有模块的引用都会指向同一个对象,属性更新后能直接获取到最新值:
// AuthUser.js const userData = { phoneNumber: null, username: null }; export async function getLoggedinUser() { try { const data = await Auth.currentAuthenticatedUser(); userData.phoneNumber = data.attributes.phone_number; userData.username = data.attributes.preferred_username; console.log('currentAuthenticatedUser() success' + userData.phoneNumber); } catch (err) { userData.phoneNumber = false; userData.username = false; console.log('currentAuthenticatedUser():' + err); } } export default userData;
在LoginPage.js中导入后,直接访问AuthUser.phoneNumber就能拿到更新后的值。
方案2:直接导出原始变量
放弃封装对象,直接导出phoneNumber和username变量,使用命名导入获取:
// AuthUser.js export let phoneNumber = null; export let username = null; export async function getLoggedinUser() { try { const data = await Auth.currentAuthenticatedUser(); phoneNumber = data.attributes.phone_number; username = data.attributes.preferred_username; console.log('currentAuthenticatedUser() success' + phoneNumber); } catch (err) { phoneNumber = false; username = false; console.log('currentAuthenticatedUser():' + err); } }
在LoginPage.js中这样使用:
import { getLoggedinUser, phoneNumber, username } from '../../config/AuthUser'; // 调用getLoggedinUser后直接访问phoneNumber即可 console.log('AuthUserSession:' + phoneNumber);
二、AWS Cognito调用成本与优化方案
关于成本
AWS Cognito的currentAuthenticatedUser()方法默认优先从本地缓存(Web端是localStorage,移动端是AsyncStorage)读取会话数据,只有缓存失效或不存在时才会调用Cognito服务端接口。正常使用场景下,重复调用不会产生额外服务端请求成本,仅在会话过期、用户重新登录或缓存被清除时才会触发服务端调用。
Cognito的收费基于月活跃用户(MAU)和API调用次数,但常规的会话验证调用属于免费额度覆盖范围,只要不是高频恶意调用,不会产生显著成本。
更优解决方案
如果想进一步减少服务端依赖、提升性能,可以结合以下方案:
本地持久化缓存:
获取用户数据后,将其存入本地存储,后续页面加载时先读本地缓存,仅当缓存不存在或过期时再调用Cognito接口刷新。示例(React Native):// AuthUser.js import AsyncStorage from '@react-native-async-storage/async-storage'; const userData = { phoneNumber: null, username: null }; // 从本地缓存加载用户数据 export async function loadCachedUser() { try { const cached = await AsyncStorage.getItem('loggedInUser'); if (cached) { const parsed = JSON.parse(cached); userData.phoneNumber = parsed.phoneNumber; userData.username = parsed.username; } } catch (err) { console.log('Load cached user failed:', err); } } export async function getLoggedinUser() { try { const data = await Auth.currentAuthenticatedUser(); userData.phoneNumber = data.attributes.phone_number; userData.username = data.attributes.preferred_username; // 保存到本地缓存 await AsyncStorage.setItem('loggedInUser', JSON.stringify(userData)); console.log('currentAuthenticatedUser() success' + userData.phoneNumber); } catch (err) { userData.phoneNumber = false; userData.username = false; await AsyncStorage.removeItem('loggedInUser'); console.log('currentAuthenticatedUser():' + err); } } export default userData;全局状态管理:
多页面应用可以用React Context API或Redux全局管理用户状态,登录成功后将数据存入全局状态,各页面直接从状态读取,无需重复调用接口或本地存储,还能方便处理登出、数据更新等场景。调整Cognito会话有效期:
Cognito的ID Token和Access Token默认有效期1小时,Refresh Token默认30天。currentAuthenticatedUser()会自动处理令牌刷新,你可以在Cognito用户池设置中根据业务需求调整有效期,减少不必要的服务端交互。
内容的提问来源于stack exchange,提问作者Jess

