Reactjs React Native:为什么FlatList在数据更改时完全重新呈现?

Reactjs React Native:为什么FlatList在数据更改时完全重新呈现?,reactjs,react-native,react-hooks,expo,react-native-flatlist,Reactjs,React Native,React Hooks,Expo,React Native Flatlist,谢谢你阅读我的问题!从几天前开始,我就一直在努力解决这个问题:每当我更改基础数据时,我的Flatlist组件都会重新呈现列表中的所有项目 情况: 我有一个平面列表组件渲染项目,其中包含一个TouchableOpacity对象,用于切换此项目的收藏夹状态 如果按下此按钮,我希望在平面列表中仅更改/重新渲染此特定项,而不是所有项。感觉上,只要我通过调用setListData更新状态,它就会重新呈现所有内容 我在一个更复杂的设置中遇到了这个问题,但能够深入到这个核心问题。或者这实际上是预期的行为

谢谢你阅读我的问题!从几天前开始,我就一直在努力解决这个问题:每当我更改基础数据时,我的Flatlist组件都会重新呈现列表中的所有项目

情况:

  • 我有一个平面列表组件渲染项目,其中包含一个TouchableOpacity对象,用于切换此项目的收藏夹状态
  • 如果按下此按钮,我希望在平面列表中仅更改/重新渲染此特定项,而不是所有项。感觉上,只要我通过调用setListData更新状态,它就会重新呈现所有内容
  • 我在一个更复杂的设置中遇到了这个问题,但能够深入到这个核心问题。或者这实际上是预期的行为
代码:

对于功能组件,您可以使用它作为
shouldComponentUpdate
的替代。 它告诉
React
何时根据上一个和下一个道具重新渲染组件

import React, { useState } from "react";
import {
  View,
  Text,
  StyleSheet,
  FlatList,
  TouchableOpacity,
} from "react-native";

const styles = StyleSheet.create({
  container: {
    flex: 1,
  }
})

const keyExtractor = (item) => item.id;

const Item = React.memo(({ item, onPressHandler }) => {
  console.log(item.name, " rendered");
  const color = item.isFav ? "red" : "green";
  return (
    <View
      style={{
        flexDirection: "row",
        width: "100%",
        margin: 10,
      }}
    >
      <Text>{item.name}</Text>
      <TouchableOpacity
        style={{ width: 100, height: 50, backgroundColor: color }}
        onPress={() => onPressHandler(item.id)}
      />
    </View>
  );
}, (prevProps, nextProps) => {
  if (prevProps.item.isFav === nextProps.item.isFav) return true;
  return false;
});

const PlanerScreen = () => {
  const [listData, setListData] = useState([
    { id: "1", name: "Banana", isFav: true },
    { id: "2", name: "Apple", isFav: false },
  ]);

  const favHandler = (id) => {
    setListData(prevState => {
      return prevState.map((item) =>
          item.id === id ? { ...item, isFav: !item.isFav } : item
        )
      }
    );
  }


  console.log("### FlatList rendered #####");
  return (
    <View style={styles.container}>
      <FlatList
        data={listData}
        renderItem={({ item }) => <Item item={item} onPressHandler={favHandler} />}
        keyExtractor={keyExtractor}
      />
    </View>
  );
};

export default PlanerScreen;
import React,{useState}来自“React”;
进口{
看法
文本,
样式表,
平面列表,
可触摸不透明度,
}从“反应本族语”;
const styles=StyleSheet.create({
容器:{
弹性:1,
}
})
const keydextractor=(item)=>item.id;
const Item=React.memo({Item,onPressHandler})=>{
console.log(item.name,“呈现”);
常量颜色=item.isFav?“红色”:“绿色”;
返回(
{item.name}
onPressHandler(item.id)}
/>
);
},(prevProps,nextProps)=>{
if(prevProps.item.isFav==nextrops.item.isFav)返回true;
返回false;
});
常量平面屏幕=()=>{
常量[listData,setListData]=useState([
{id:“1”,name:“Banana”,isFav:true},
{id:“2”,name:“Apple”,isFav:false},
]);
常数favHandler=(id)=>{
setListData(prevState=>{
返回prevState.map((项)=>
item.id==id?{…item,isFav:!item.isFav}:item
)
}
);
}
console.log(“##########””;
返回(
}
keyExtractor={keyExtractor}
/>
);
};
导出默认平面屏幕;

您将在
计划屏幕上设置状态,然后重新呈现整个
平面列表。您应该问的问题是:-重新渲染是否会影响您的性能?确实如此,因为我在平面列表中的每个项目中都有小缩略图,并且平面列表包含>100个项目(在更复杂的上下文中)。在每次状态更改时,项目中的所有图像都会因重新渲染而闪烁。谢谢,效果非常好!这正是我想要的,你刚刚救了我的周末:)
FlatList rendered
Banana  rendered
Apple  rendered
FlatList rendered
Banana  rendered
Apple  rendered
FlatList rendered
Banana  rendered
Apple  rendered
import React, { useState } from "react";
import {
  View,
  Text,
  StyleSheet,
  FlatList,
  TouchableOpacity,
} from "react-native";

const styles = StyleSheet.create({
  container: {
    flex: 1,
  }
})

const keyExtractor = (item) => item.id;

const Item = React.memo(({ item, onPressHandler }) => {
  console.log(item.name, " rendered");
  const color = item.isFav ? "red" : "green";
  return (
    <View
      style={{
        flexDirection: "row",
        width: "100%",
        margin: 10,
      }}
    >
      <Text>{item.name}</Text>
      <TouchableOpacity
        style={{ width: 100, height: 50, backgroundColor: color }}
        onPress={() => onPressHandler(item.id)}
      />
    </View>
  );
}, (prevProps, nextProps) => {
  if (prevProps.item.isFav === nextProps.item.isFav) return true;
  return false;
});

const PlanerScreen = () => {
  const [listData, setListData] = useState([
    { id: "1", name: "Banana", isFav: true },
    { id: "2", name: "Apple", isFav: false },
  ]);

  const favHandler = (id) => {
    setListData(prevState => {
      return prevState.map((item) =>
          item.id === id ? { ...item, isFav: !item.isFav } : item
        )
      }
    );
  }


  console.log("### FlatList rendered #####");
  return (
    <View style={styles.container}>
      <FlatList
        data={listData}
        renderItem={({ item }) => <Item item={item} onPressHandler={favHandler} />}
        keyExtractor={keyExtractor}
      />
    </View>
  );
};

export default PlanerScreen;