繁体   English   中英

每次滚动屏幕时,FlatList 都会重新渲染项目

[英]FlatList is re-rendering items everytime screen is scrolled

我有一个包含 300 个项目的列表。 我正在使用 FlatList 来呈现项目。

问题:

  • 滚动屏幕时列出重新渲染的项目。 即使我已经将组件包装在 React.memo 中。

我尝试通过调整windowSizemaxToRenderPerBatch来优化列表,但问题仍然存在。

您可以在下面的沙箱链接中查看代码。

先感谢您 !

https://codesandbox.io/s/gracious-dhawan-i4d51h?file=/src/App.js

下面是代码片段

const data = [
{
    id: 1,
    first_name: "Shaina",
    last_name: "Osorio",
    email: "sosorio0@a8.net"
  },
  {
    id: 2,
    first_name: "Ania",
    last_name: "Cotilard",
    email: "acotilard1@about.me"
  },
  {
    id: 3,
    first_name: "Hagen",
    last_name: "Lisciandri",
    email: "hlisciandri2@nature.com"
  }
]

 const isEqual = (prev, next) => { return true; }; const RenderItem = React.memo((props) => { const { id, first_name, email } = props; console.log("id >>> ", id); return ( <View style={{ padding: 5, backgroundColor: "lightblue", marginVertical: 3 }} > <Text>First Name: {first_name}</Text> <Text>Email: {email}</Text> </View> ); }, isEqual); function App() { return ( <View style={{ flex: 1 }}> <FlatList data={data} renderItem={({ item }) => ( <RenderItem id={item.id} first_name={item.first_name} email={item.email} /> )} initialNumToRender={15} maxToRenderPerBatch={15} keyExtractor={(item) => item.id} /> </View> ); } export default App;

在您的示例中,您正在您的 renderItem 中记录,因此当新元素进入渲染区域时,它会被记录。 滚动时会发生这种情况。 但这并不意味着整个列表都会被重新渲染。 只需在托管列表的组件中直接放置一个 conosle.log,您会看到它只渲染一次,这与 renderItem 不同,它是在每次滚动创建新项目时渲染的。

const App = ()=> {
  console.log("Entire List Rerendered");
  return (
    <View style={{ flex: 1 }}>
      <FlatList
        data={data}
        renderItem={rendering}
        initialNumToRender={5}
        maxToRenderPerBatch={5}
        keyExtractor={(item) => item.id}
      />
    </View>
  );
}

Flashlist 可能会有所帮助,因为它会回收 renderItems 并且不会像 Flatlist 那样销毁它们。 但是你应该更好地测试它。

你能把它定义为一个单独的 function

const rendering = ({ item }) => {
  return (
    <RenderItem
      id={item.id}
      first_name={item.first_name}
      email={item.email}
    />
  )
}

然后在你的平面清单上调用它?

<FlatList
  data={data}
  renderItem={rendering}
  initialNumToRender={15}
  maxToRenderPerBatch={15}
  keyExtractor={(item) => item.id}
/>

内联事件处理程序是匿名函数。 每次组件渲染时都会创建它们。

更新

提取你的 render 和 keyExtractor 函数,并像这样用 useCallback 包围它们

function App() {
  const rendering = useCallback(({item}) => {
    console.log("id >>> ", item.id);
    return (
      <View
      style={{
        padding: 5,
        backgroundColor: "lightblue",
        marginVertical: 3
      }}
    >
      <Text>First Name : {item.first_name}</Text>
      <Text>Email : {item.email}</Text>
    </View>
    )
  }, []);

  const keyExtractoring = useCallback((item) => {
    return item.id.toString();
  }, []);

  return (
    <View style={{ flex: 1 }}>
      <FlatList
        data={data}
        renderItem={rendering}
        initialNumToRender={5}
        maxToRenderPerBatch={5}
        keyExtractor={keyExtractoring}
      />
    </View>
  );
}

更新的小提琴

查看 Shopify 的 FlashList,他们说它比 Flatlist 优化得多。 也许它可以满足您的需求。 尝试没有害处:点击这里

    import React from "react";
    import { View, Text, StatusBar } from "react-native";
    import { FlashList } from "@shopify/flash-list";
    
    const DATA = [
      {
        title: "First Item",
      },
      {
        title: "Second Item",
      },
    ];
    
    const MyList = () => {
      return (
        <FlashList
          data={DATA}
          renderItem={({ item }) => <Text>{item.title}</Text>}
          estimatedItemSize={200}
        />
      );
    };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM