You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键修改点

  1. 移除冗余state:删除getStationsId相关的state,直接使用接口返回的数据过滤,避免异步更新问题。
  2. 优化初始值:将list和filterRecord的初始值从空字符串改为空数组,符合列表数据的类型预期。
  3. 明确变量命名:将从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:20:35