React Native如何先从AsyncStorage设置sessionId后再发起API请求
问题原因
- 两个异步函数没有按预期顺序执行:
settingSession调用后没有等待执行完成就直接触发InitList,此时sessionId还是初始的null - React的
setState是异步更新逻辑,就算你等待settingSession执行完,当前作用域下的sessionId还是初始值,不会立刻更新为读取到的userId
修复方案
方案1(更推荐,避免闭包问题)
直接把从AsyncStorage读取到的userId作为参数传给InitList,不需要依赖state中的sessionId:
const [sessionId, setSessionId] = useState(null); const settingSession = async () => { const userId = await AsyncStorage.getItem('userId'); setSessionId(userId); return userId; // 把读取到的userId返回 } useEffect(() => { // 封装一层async函数处理执行顺序 const init = async () => { const userId = await settingSession(); // 等待session设置完成后,再调用列表接口,直接传参 InitList(userId); } init(); }, []); // 新增参数接收sessionId,不依赖外部state const InitList = async (currentSessionId) => { var requestOptions = { method: 'GET', redirect: 'follow' }; try { // 直接用传入的currentSessionId,避免state更新延迟问题 const response = await fetch("http://127.0.0.1:8080/skyzerguide/referenceGuideFunctions/tetra/user/" + currentSessionId, requestOptions) const status = await response.status; const responseJson = await response.json(); if (status == 204) { throw new Error('204 - No Content'); } else { setMasterDataSource(responseJson); } } catch (error) { console.log(error); return false; } }
方案2:监听sessionId变化触发接口调用
如果你需要保留依赖state的写法,可以拆分useEffect,监听sessionId的变化,只有当sessionId有值时才调用InitList:
const [sessionId, setSessionId] = useState(null); const settingSession = async () => { const val = await AsyncStorage.getItem('userId'); setSessionId(val); } const InitList = async () => { // 先加判断,sessionId为空时不发起请求 if(!sessionId) return; var requestOptions = { method: 'GET', redirect: 'follow' }; try { const response = await fetch("http://127.0.0.1:8080/skyzerguide/referenceGuideFunctions/tetra/user/" + sessionId, requestOptions) const status = await response.status; const responseJson = await response.json(); if (status == 204) { throw new Error('204 - No Content'); } else { setMasterDataSource(responseJson); } } catch (error) { console.log(error); return false; } } // 第一个useEffect只负责初始化session useEffect(() => { settingSession(); }, []); // 第二个useEffect监听sessionId变化,有值时调用接口 useEffect(() => { if(sessionId) { InitList(); } }, [sessionId]);
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

