我在做什么?
尝试根据state.data
中存储的某些项目呈现FlatList。存在一个按钮,按下后会在state.data
中添加一个新项目。
出了什么问题?
在按下按钮时,我期望renderItem只能被调用state.data.length
次,而被调用2*state.data.length
次。另外,这种2x行为并不总是一致的,并且随着state.data.length
的增加而变化。
Ex:当state.data.length=3
时,则在初始渲染时,renderItem的调用次数恰好是3次,这与state.data
中的项目数相同,并且在按下向其追加新项目的按钮时state.data
和现在的state.data.length=4
和renderItem被调用8次,即2*state.data.length
次。
但是,当state.data.length=11
时,则在初始渲染时,renderItem恰好被调用了21次,并在按下按钮时将一个新项附加到state.data
到现在的state.data.length=12
上,并且renderItem被称为23偏离2*state.data.length
行为的时间。
我期望什么?
renderItem在初始和后续渲染中仅被调用state.data.length
次。
我尝试了什么?
state.data
来使用它们确实减少了renderItem的调用次数,但仍然没有太大的减少。我面临的真正问题是当我试图在FlatList中呈现聊天消息(通过API调用获取并将其设置在状态内)时。现在,大约有200条消息,其renderItem在800-1200次范围内被调用,这对性能造成了影响。
这种行为是否偏离了我的预期? 如果是,那么背后的逻辑是什么。如果没有,那我在做什么错了?
答案 0 :(得分:1)
我仔细阅读了您的代码,并试图理解您的担忧。
(renderItem〜FlatList的prop) 注意:-使用平面列表时,您的列表项应为纯组件或应实现shouldComponentUpdate,否则它们将提供比预期更多的时间
因此,请牢记以下几点,即按照所述实施了您的平面清单项目。
甚至我都不知道事情是如何实现的,但是根据我在文档中阅读的内容,我只会分享一些可能有帮助的内容。
“”为了限制内存并实现流畅的滚动,将内容异步显示在屏幕外。这意味着滚动速度可能比填充速率快,并且暂时看到空白内容。这是一个折衷方案,可以进行调整以适合每个应用程序的需求,我们正在努力在幕后对其进行改进。”
这是少数道具的默认值,有助于控制权衡
maxToRenderPerBatch:10,
onEndReachedThreshold:2,//长度的倍数
scrollEventThrottle:50,
updateCellsBatchingPeriod:50,
windowSize:21,//长度的倍数
为了更清楚地理解,我们需要了解VirtualizedList的实现方式。在进一步挖掘之后,我一定会更新此答案。
答案 1 :(得分:0)
遇到同样的问题,我的问题是将箭头函数作为道具传递,我设法通过将我的所有fnProp={() => {}}
替换为fnProp={someFunc}
另一种解决方案是使用shouldComponentUpdate
。作为FlatList中用作renderItem道具的项目“ YourWrappedItem”,您可以使用这样的包装器组件:
class ItemToRender extends Component {
shouldComponentUpdate() {
return false
}
render() {
return (
<YourWrappedItem {...someProps}>
Example
</YourWrappedItem>
)
}
}
希望它对某人有帮助。
答案 2 :(得分:0)
使用 React.memo 解决这个问题
<FlatList
renderItem={({item, index}) => <DisplayRenderMemo item={item} index={index} onPress = { async() => { } }/> }
/>
const DisplayRenderMemo = React.memo(({ item, index, onPress }) =>
{
const count = React.useRef(0);
return (
<TouchableOpacity
key={index}
onPress={onPress}>
<Text>{item.label} {(count.current++)} counts</Text>
</TouchableOpacity>
)
}, (prevProps, nextProps) => {
console.log(nextProps, prevProps);
return nextProps.item.data_id === prevProps.item.data_id
})
首先检查不使用 React.memo 之类的
const DisplayRenderMemo = ({ item, index, onPress }) =>
{
const count = React.useRef(0);
return (
<TouchableOpacity
key={index}
onPress={onPress}>
<Text>{item.label} {(count.current++)} counts</Text>
</TouchableOpacity>
)
}
现在显示为 0, 1, 2, 3 个计数
然后像上面提到的代码一样使用 React.memo
万岁!!!现在它只显示 0 计数。所以我们得到了解决方案。它没有重新渲染。
注意:请确保 {item}
数据中哪个字段是唯一的。因为我们不能将索引用作唯一的。因此,只需将任何唯一键与您的 {item}
数据一起传递。原因是如果我们获取新的数据集来替换现有数据,则该现有数据集由索引控制在 react.memo 中。因此,不会重新渲染相同的索引项以在平面列表中查看