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

React Native 调用setState更新数组类型state失败问题求助

问题根因

  • 闭包陷阱+setState异步特性:countrySearchAPI函数首次执行时,捕获的countryDetails永远是初始值[],循环中每次执行setCountryDetails时展开的都是这个初始空数组,前一次的更新结果会被后一次直接覆盖,最终只能保留最后一次循环存入的国家数据。同时setState不会同步更新当前作用域下的state变量,所以你在set之后立刻打印拿到的始终是旧值。
  • 循环内串行请求效率低:逐个await第二个接口会大幅拉长请求总耗时。
  • FlatList key提取逻辑错误:你存储的国家对象中没有id字段,后续打开FlatList注释会直接报错。

修复方案

推荐先批量拉取所有国家详情,全部获取完成后一次性更新state,代码示例如下:

import React, { useState, useEffect } from "react";
import {
  Platform,
  Text,
  View,
  TextInput,
  StyleSheet,
  FlatList,
} from "react-native";
import { FontAwesome } from "react-native-vector-icons";
import countryapi from "../src/countryapi";

const CountryScreen = () => {
  const [countryDetails, setCountryDetails] = useState([]);

  const countrySearchAPI = async () => {
    try {
      const countriesData = await countryapi.get();
      const countries = countriesData.data;

      // 批量生成所有详情请求
      const detailRequests = countries.map(async (country) => {
        const { iso2 } = country;
        const countriesDetailsData = await countryapi.get(`/${iso2}`);
        const { name, iso3, emoji } = countriesDetailsData.data;
        return {
          countryName: name,
          iso3,
          iso2,
          countryFlag: emoji,
        };
      });

      // 等待所有请求完成
      const allCountryDetails = await Promise.all(detailRequests);
      // 一次性更新state
      setCountryDetails(allCountryDetails);
      console.log(allCountryDetails);
    } catch (e) {
      console.log(e);
    }
  };

  useEffect(() => {
    countrySearchAPI();
  }, []);

  return (
    <View>
      <View style={styles.searchSection}>
        <FontAwesome name="search" size={30} />
        <TextInput placeholder="搜索国家" style={styles.inputBox} />
      </View>
      <FlatList
        data={countryDetails}
        renderItem={({ item }) => {
          return (
            <Text>
              {item.countryName} {item.countryFlag}
            </Text>
          );
        }}
        // 用唯一的iso2作为key,替换原来不存在的id
        keyExtractor={(item) => item.iso2}
      />
    </View>
  );
};

如果你确实需要逐个请求逐个更新,就把setState改为函数式更新形式即可,它可以拿到上一次更新后的最新state值:

setCountryDetails(prev => [
  ...prev,
  {
    countryName: name,
    iso3,
    iso2,
    countryFlag: emoji,
  },
]);

内容的提问来源于stack exchange,提问作者tulipz123

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 23:06:04