React Native首次加载无法通过AsyncStorage的userId过滤数据
问题解决:React Native首次加载无法过滤接口数据
问题背景
通过接口http://localhost/api/offer/get-offerlist?id=${userId}获取数据,其中userId从React Native的AsyncStorage读取。接口响应数据结构如下:
[{ "_id": "6369553f0617161cf0e7c991", "location": { "coordinates": [-0.127585,51.5072167], "type": "Point" }, "option": { "enum": ["Charging Station"], "type": "Point" }, "userId": "635696833ab4103a08f96713", "name": "ISLAMABAD", "buildingName": "Habib Bank Plaza", "rate": 0.5, "longitude": "-0.127585", "latitude": "51.5072167", "locationShortDescription": "Habib Bank Plaza building near II Chandigar Road", "__v": 0, "result": [{ "_id": "636bb6104395231b5c212bab", "request": { "enum": [{"enum": [0]}] }, "offerUserId": "635696833ab4103a08f96713", "stationId": "6369553f0617161cf0e7c991", "rate": 0.2, "__v": 0 },{ "_id": "636bcc5c0f20bf1484c92be0", "request": { "enum": [{"enum": [0]}] }, "adUserId": "635696833ab4103a08f96713", "offerUserId": "635696833ab4103a08f96713", "stationId": "6369553f0617161cf0e7c991", "rate": 1.6, "__v": 0 }] }]
尝试用filter和some方法匹配_id与result中的stationId时,首次加载数据无法过滤,刷新屏幕后才能成功获取并过滤。
错误原因
原代码中调用setGetStationsId(extractedStationId)后立刻使用getStationsId过滤,但React的setState是异步操作,此时getStationsId仍为初始空字符串,导致过滤逻辑失效。刷新后组件重新渲染,getStationsId已存储之前的值,过滤才成功。
修复方案
无需将提取的stationId存入state,直接使用接口返回的data中每个item的result数组进行过滤,避开异步state更新的问题。同时优化state初始值为更合理的空数组。
修改后的业务代码
import { useState, useEffect } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; const YourComponent = () => { const [userId, setUserID] = useState(""); const [list, setList] = useState([]); // 初始值设为空数组 const [loading, setLoading] = useState(false); const [filterRecord, setFilterRecord] = useState([]); // 初始值设为空数组 const getOfferList = async () => { try { setLoading(true); const storedUserId = await AsyncStorage.getItem('userId'); setUserID(storedUserId); const response = await fetch( `http://localhost/api/offer/get-offerlist?id=${storedUserId}`, { headers: { accept: 'application/json', 'Content-Type': 'application/json' }, }, ); const data = await response.json(); // 直接基于当前item的result数组过滤,无需依赖state const myArrayFiltered = data.filter(el => { // 根据业务需求调整条件: // 若筛选当前用户的offer对应的station,使用:return el.result.some(f => f.offerUserId === storedUserId); // 若保留原逻辑(匹配item.userId与result中的offerUserId),保留下面的代码: return el.result.some(f => f.offerUserId === el.userId); }); setLoading(false); setList(data); setFilterRecord(myArrayFiltered); } catch (e) { console.log(e); setLoading(false); } }; useEffect(() => { getOfferList(); }, []); // ... 界面代码部分 }; export default YourComponent;
关键修改点
- 移除冗余state:删除
getStationsId相关的state,直接使用接口返回的数据过滤,避免异步更新问题。 - 优化初始值:将
list和filterRecord的初始值从空字符串改为空数组,符合列表数据的类型预期。 - 明确变量命名:将从AsyncStorage获取的userId命名为
storedUserId,避免与state中的userId混淆。
界面代码优化提示
原界面代码中item.result[0].rate和item.result[0].createdAt存在报错风险(若result为空数组),建议添加可选链操作:
const renderItem = ({item}) => ( <Item name={item.name} buildingName={item.buildingName} locationShortDescription={item.locationShortDescription} latitude={item.latitude} longitude={item.longitude} rate={item.rate} userRate={item.result?.[0]?.rate} // 添加可选链 createdAt={item.result?.[0]?.createdAt} // 添加可选链 /> );
内容的提问来源于stack exchange,提问作者Hasnain Askari
相关产品推荐
相关产品推荐

