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

React Native从JSON API追加数据的最优方案及性能问题解决

问题根源及解决方案

1. 核心问题:重复请求相同数据导致数据冗余

你的loadMoreData每次请求的都是同一个API地址,没有传递分页参数,导致每次返回的10条数据都是重复的。data数组不断累积重复项,到50-60条时实际是重复了5-6次的相同内容,FlatList需要渲染的项暴增,直接拖慢了应用性能。

2. 次要问题:不必要的组件重渲染

  • renderItem里的<Text>组件没有做memo化处理,每次data更新时,所有可见的列表项都会重新渲染
  • loadMoreData函数没有被稳定化,导致每次组件渲染时都会创建新的函数实例,触发Button的不必要重渲染
  • 状态更新依赖当前data快照,存在闭包风险,异步请求完成时可能拿到旧的data状态

修复后的完整代码

import React, { useState, useEffect, useCallback } from 'react';
import { View, Text, Button, FlatList, ActivityIndicator } from 'react-native';

const API_URL = 'https://my-api-url.com/data';

// 把列表项组件memo化,避免不必要重渲染
const ListItem = React.memo(({ item }) => {
  return <Text>{item.name}</Text>;
});

const App = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [isLoading, setIsLoading] = useState(false);

  // 用useCallback稳定函数引用
  const fetchData = useCallback(async (currentPage = 1) => {
    setIsLoading(true);
    try {
      // 传递分页参数给API,获取对应页码的数据
      const response = await fetch(`${API_URL}?page=${currentPage}`);
      const jsonData = await response.json();
      if (currentPage === 1) {
        // 首次加载直接替换数据
        setData(jsonData);
      } else {
        // 加载更多用函数式更新,避免依赖当前data的闭包问题
        setData(prevData => [...prevData, ...jsonData]);
      }
    } catch (error) {
      console.error(error);
    } finally {
      setIsLoading(false);
    }
  }, []);

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

  const loadMoreData = useCallback(async () => {
    if (isLoading) return; // 防止重复加载
    const nextPage = page + 1;
    await fetchData(nextPage);
    setPage(nextPage);
  }, [page, isLoading, fetchData]);

  return (
    <View>
      <FlatList
        data={data}
        renderItem={({ item }) => <ListItem item={item} />}
        keyExtractor={(item) => item.id.toString()}
        // FlatList性能优化参数
        removeClippedSubviews={true}
        maxToRenderPerBatch={10}
        windowSize={5}
      />
      <View style={{ padding: 10 }}>
        {isLoading ? (
          <ActivityIndicator size="small" color="#0000ff" />
        ) : (
          <Button title="Load more" onPress={loadMoreData} />
        )}
      </View>
    </View>
  );
};

export default App;

关键优化点说明

  • 分页参数传递:给API添加page参数,确保每次加载更多都获取新的10条数据,避免数据冗余
  • memo化列表项:用React.memo包裹ListItem,只有当item变化时才重新渲染
  • 稳定函数引用:用useCallback包裹fetchData和loadMoreData,避免因函数实例变化导致的组件重渲染
  • 函数式状态更新:setData(prevData => [...prevData, ...jsonData]),不依赖当前data的快照,避免异步请求中的闭包问题
  • 加载状态控制:添加isLoading状态,防止重复点击Load More按钮
  • FlatList性能参数:设置removeClippedSubviews、maxToRenderPerBatch、windowSize,优化列表渲染性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:38:08