FlatList 在添加新数据时重新渲染所有数据

2024-01-18

我测试了 FlatList。这是我想做的:
1.使用componentDidmount获取10条初始数据
2. 向下滚动可获取另外 10 条数据

App.js

import React from 'react';
import {
  View,
  SafeAreaView,
  Text,
  FlatList,
} from 'react-native';
import throttle from 'lodash.throttle';
import { tmpPosts } from './src/data/tmpdata';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.page = 0;
    this.state = {
      posts: [],
    };
    this.getMoreDataThrottled = throttle(this.getMoreData, 3000);
  }

  componentDidMount() {
    console.log('comoponentDidMount')
    this.getMoreDataThrottled();
  }

  componentWillUnmount() {
    this.getMoreDataThrottled.cancel();
  }

  getMoreData = () => {
    console.log('start getMoreData')
    const tmpList = []
    for (let i = 0; i < 10; i++ ) {
      tmpList.push(tmpPosts[this.page])
      this.page += 1;
    }

    this.setState(prevState => ({
      posts: prevState.posts.concat(tmpList)
    }));
  }

  renderPost = ({item}) => {
    console.log(item.id)
    return (
      <View style={{height: 200}}>
        <Text>{item.id}</Text>
      </View>
    );
  };

  render() {
    return (
      <SafeAreaView>
        <FlatList
          data={this.state.posts}
          renderItem={this.renderPost}
          keyExtractor={post => String(post.id)}
          initialNumToRender={10}
          onEndReachedThreshold={0.01}
          onEndReached={this.getMoreDataThrottled}
        />
      </SafeAreaView>
    );
  }
}

export default App;

tmpdata.js

let num = 0;
export const tmpPosts = [
  {id: String(num += 1)},
  {id: String(num += 1)},
  .
  .
  .
]

我实现了我想要的,但是渲染发生了很多。
这是console.log

comoponentDidMount
start getMoreData
1
2
3
.
.
.
8
9
10
1
2
3
.
.
.
8
9
10
start getMoreData
1
2
3
.
.
.
8
9
10
1
2
3
.
.
.
18
19
20
start getMoreData
1
2
3
.
.
.
18
19
20
1
2
3
.
.
.
28
29
30

看来日志的意思是:
1、每次都会重新渲染两次。
2. FlatList渲染num增加,因为它也渲染旧数据。

我检查了类似的问题,这似乎是 FlatList 的正常行为。
FlatList renderItem 被调用多次 https://stackoverflow.com/questions/51365912/flatlist-renderitem-is-called-multiple-times
FlatList 调用两次 https://stackoverflow.com/questions/48357524/flatlist-calling-twice
https://github.com/facebook/react-native/issues/14528 https://github.com/facebook/react-native/issues/14528

不过我担心当数据达到100以上时应用程序会变慢并崩溃。
FlatList 性能的最佳解决方案是什么?
shouldComponentUpdate 防止不必要的重新渲染,例如已经渲染的旧数据?


Update

抱歉,我的回复不完整。我重现了您的问题,并通过将“发布”组件移动到单独的文件中来修复它。 这篇文章扩展了 pureComponent,所以如果它的 props 没有改变,它就不会重新渲染。

class App extends React.Component {
  constructor(props) {
    super(props);
    this.page = 0;
    this.state = {
      posts: []
    };
    this.getMoreDataThrottled = throttle(this.getMoreData, 3000);
  }

  componentDidMount() {
    console.log("comoponentDidMount");
    this.getMoreData();
  }

  componentWillUnmount() {
    this.getMoreDataThrottled.cancel();
  }

  getMoreData = () => {
    console.log("start getMoreData");
    const tmpList = [];
    for (let i = 0; i < 10; i++) {
      tmpList.push(tmpPosts[this.page]);
      this.page += 1;
    }

    this.setState(prevState => ({
      posts: prevState.posts.concat(tmpList)
    }));
  };

  renderPost = ({ item }) => {
    return <Post item={item} />;
  };

  render() {
    return (
      <SafeAreaView>
        <FlatList
          data={this.state.posts}
          renderItem={this.renderPost}
          keyExtractor={post => String(post.id)}
          initialNumToRender={10}
          onEndReachedThreshold={0.5}
          onEndReached={this.getMoreData}
        />
      </SafeAreaView>
    );
  }
}

/*
  In a separate file
*/
class Post extends React.PureComponent {
  render() {
    const { item } = this.props;
    console.log(item.id);
    return (
      <View key={item.id} style={{ height: 200 }}>
        <Text>{item.id}</Text>
      </View>
    );
  }
}

// Same but in functional (my preference)
const _PostItem =({ item }) => {
  console.log(item.id);
  return (
    <View key={item.id} style={{ height: 200 }}>
      <Text>{item.id}</Text>
    </View>
  );
};

export const PostFunctionalWay = React.memo(_PostItem);

export default App;

原答案

我认为您忘记在您的平面列表中添加道具“extraData”:

<FlatList
          data={this.state.posts}
          extraData={this.state.posts}
          renderItem={this.renderPost}
          keyExtractor={post => String(post.id)}
          initialNumToRender={10}
          onEndReachedThreshold={0.01}
          onEndReached={this.getMoreDataThrottled}
/>

https://facebook.github.io/react-native/docs/flatlist#extradata https://facebook.github.io/react-native/docs/flatlist#extradata

PS:也许可以扩展 PureComponent

PS2:您需要渲染项目(renderPost)有一个带有唯一键的道具“id”

 renderPost = ({item}) => {
    console.log(item.id)
    return (
      <View id={item.id} style={{height: 200}}>
        <Text>{item.id}</Text>
      </View>
    );
  };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FlatList 在添加新数据时重新渲染所有数据 的相关文章

随机推荐

  • 浏览器将边框值截断为整数

    每当非整数像素值用于元素的边框时 浏览器都会将该值截断为整数 为什么会这样呢 我知道边境不会actually占用像素的一部分 但这些类型的值有时与其他值结合使用以形成完整像素 例如 宽度为 1 6px 的左右边框应导致元素的总宽度增加 3p
  • Console.Clear() 闪烁

    while true Console Clear for int row 0 row lt 50 row for int col 0 col lt 50 col Console Write world row col Console Wri
  • 当原始对象更改时,绑定不会更新

    我想我误解了 Angular 中数据绑定和作用域的工作原理 或者我对 Javascript 有一些误解 我希望有人能帮助我 假设我有一个工厂 它有一个对象 并为其定义了一个 getter setter app factory myFacto
  • Tkinter 滚动条不滚动

    我正在尝试创建一个带有两个画布和一个滚动条的图形用户界面 同时穿过这两个画布 作为另一个项目的测试 我创建了根 两个画布 并使用网格方法将一些标签固定到每个画布上 并创建了滚动条 但是 当我运行该程序时 滚动条会移动 但窗口的内容根本没有改
  • 在 Java 中管理 XAdES 签名的库 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个允许创建和验证 XAdES 签名的 Java 库 格式越多越好 XAdES BES XAd
  • 二维unordered_map

    typedef boost unordered map
  • 为什么即使对象指针在多重继承中不同,情况也是一样的?

    当使用多重继承时 C 必须维护多个 vtable 这导致对公共基类有 多个视图 这是一个代码片段 include stdafx h include
  • 具有非静态 lambda 成员的类不能使用默认模板参数吗?

    这个小测试程序 include
  • 通过 .htaccess 从 URL 中删除双斜杠或更多斜杠时出现问题

    我使用以下 htaccess 规则从 Web url 中删除双斜杠或多个斜杠 remove double more slashes in url RewriteCond REQUEST URI RewriteRule 1 2 R 301 L
  • 选定列的高图表不同颜色

    Highcharts 中不同的选定列是否可以有不同的颜色 这是我想做的事情的草图 http jsfiddle net jZmYW 4 http jsfiddle net jZmYW 4 选择一个点 列 时 它应该具有特定的颜色 我尝试通过为
  • XSLT 字符串替换

    我不太了解 XSL 但我需要修复这段代码 我已经减少了它以使其更简单 我收到这个错误 无效的 XSLT XPath 函数 在这条线上
  • Java MVC Web开发框架?

    我想用java开发一个网站 但我在java web开发方面是绝对的初学者 我想使用一个使用 MVC 模式和 Ajax 的框架 我做了一些搜索 发现 Spring 或 Struts 合适 但我不确定 您能推荐一个框架吗 游戏框架 http w
  • .NET - 从非托管数组复制到非托管数组

    我一直在查看 Marshal 类 但似乎找不到允许我从非托管数组 IntPtr 复制到另一个非托管数组 IntPtr 的方法 使用 NET 可以实现这一点吗 您还可以通过 DllImport RtlMoveMemory 来完成工作 DllI
  • 如何使用谷歌翻译应用程序

    我编写了有关字典句子的程序 我希望有功能可以在我的应用程序中转到 谷歌翻译 应用程序 我该如何使用它 我应该导入什么东西吗 据我所知 谷歌翻译 Android 应用程序没有公开任何标准Intent是你可以使用的 很遗憾 但同时也很奇怪 你会
  • Perl 意外行为:croak 与 try catch

    我看到一些异常指向 catch 块本身 参见下面的示例 在我看来 这是一个意想不到的行为 因为它改变了原始异常的位置并使得调试变得困难 应该说在第 13 行处死亡 如果我使用 die confess 或使用 eval 代替 try catc
  • FirebaseApp:Firebase API 初始化失败

    我遇到了由 Firebase Api 引起的错误 这是错误日志 Firebase API initialization failure java lang reflect InvocationTargetException Caused b
  • 哪个 C# 程序集包含 Invoke?

    另一个问题 为什么 VS10 如此热衷于抱怨 Invoke 在我不断追求让我的应用程序工作成为世界上最好的 C 程序员的过程中 我认为线程是一件好事 MSDN 有一篇关于制作的有用文章对控件的线程安全调用 http msdn microso
  • 传递对象时 Axios POST 请求不起作用

    我正在尝试使用 axios 在 vue js 应用程序中向本地 API 发出发布请求 并且响应返回空数据 使用 Postman 工具 API 上的 post 请求工作正常 下面是我的代码 var the data title This is
  • WebClient DownloadString 不返回任何内容

    我想从海盗湾的搜索查询中获取源代码 我的代码中有这个 但它不返回任何内容 WebClient webpage new WebClient string source webpage DownloadString http thepirate
  • FlatList 在添加新数据时重新渲染所有数据

    我测试了 FlatList 这是我想做的 1 使用componentDidmount获取10条初始数据2 向下滚动可获取另外 10 条数据 App js import React from react import View SafeAre