简体   繁体   English

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

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

I have a list of 300 items.我有一个包含 300 个项目的列表。 I'm using FlatList to render the items.我正在使用 FlatList 来呈现项目。

ISSUE:问题:

  • List items re-rendering when I scroll the screen.滚动屏幕时列出重新渲染的项目。 Even when I have wrapped the component in React.memo.即使我已经将组件包装在 React.memo 中。

I tried to optimise the list by tweaking the windowSize , maxToRenderPerBatch but the issue still persist.我尝试通过调整windowSizemaxToRenderPerBatch来优化列表,但问题仍然存在。

You can check the code in below sandbox link.您可以在下面的沙箱链接中查看代码。

Thankyou in advance !先感谢您 !

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

Below is the code snippet下面是代码片段

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;

In your example, you are logging inside your renderItem, so when a new element comes into the rendered area, it is logged.在您的示例中,您正在您的 renderItem 中记录,因此当新元素进入渲染区域时,它会被记录。 This happens when you scroll.滚动时会发生这种情况。 But this doesn't mean that the whole list will be re-rendered.但这并不意味着整个列表都会被重新渲染。 Just place a conosle.log directly in the component that hosts the list, and you'll see that it's only rendered once, unlike the renderItem, which is rendered every time a new item is created by a scroll.只需在托管列表的组件中直接放置一个 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 might help, because it recycles renderItems and doesn't destroy them like Flatlist does. Flashlist 可能会有所帮助,因为它会回收 renderItems 并且不会像 Flatlist 那样销毁它们。 But you should test that better.但是你应该更好地测试它。

Can you define it as a separate function你能把它定义为一个单独的 function

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

and then call it on your flat list?然后在你的平面清单上调用它?

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

Inline event handlers are anonymous functions.内联事件处理程序是匿名函数。 They are created every time the component renders.每次组件渲染时都会创建它们。

UPDATE更新

Extract your render and keyExtractor functions and surround them with useCallback like that提取你的 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>
  );
}

Updated fiddle 更新的小提琴

Check out FlashList by Shopify they are saying that it is much more optimized than Flatlist.查看 Shopify 的 FlashList,他们说它比 Flatlist 优化得多。 maybe it can meet your needs.也许它可以满足您的需求。 no harm in trying: Click Here尝试没有害处:点击这里

    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