【发布时间】:2019-02-06 20:24:36
【问题描述】:
我有一个 FlatList,其中填充了大约 18000 个文本行。因为每一行中的文本是可变长度的,所以我无法提供静态高度供 getItemLayout 使用。
我正在尝试做的是首先使用一个虚拟视图遍历整个数据集,我通过 onLayout 从中收集高度维度。我的问题是,目前,视图在停止之前只重新渲染了大约 10 次。据我所知,对于最终出现在屏幕上的最后一个视图,根本不会调用 onLayout —— 这又是第 10 个(或者大约,取决于我遍历数据的时间间隔)。
下面是我的代码,我在这里尝试对其进行了一些简化。目前只是试图找到一种方法来迭代并预先计算整个数据集的视图高度,然后在单独的组件中进行渲染。
import React, { Component } from 'react';
import { AppRegistry, Text, View, TouchableOpacity, StyleSheet } from 'react-native';
export default class DummyMainItem extends Component {
constructor(props) {
super(props);
this.state = {
codeData: [],
currentItem: -1,
};
}
componentWillReceiveProps(nextProps) {
// Get data from MainFlatList
if (nextProps.codeData != '') {
console.log("PROPS in DummyMainItem are codeData of length: " + nextProps.codeData.length);
this.setState({ codeData: nextProps.codeData });
}
}
getItemDimensions(layout) {
const { x, y, width, height } = layout;
curItem = this.state.currentItem;
console.log("getItemDimensions of #" + curItem + " (width, height) : (" + width + ", " + height + ")");
if (curItem <= this.state.codeData.length) {
this.setState({ currentItem: curItem + 1 });
}
}
render() {
console.log("Dummy Rendering item #" + this.state.currentItem);
if (this.state.codeData != null && this.state.codeData.length > 0) {
var item = this.state.codeData[this.state.currentItem];
switch (item.type) {
case '0':
console.log("Dummy Case 0 FULLTEXT: " + item.fulltext);
return (
<TouchableOpacity>
<View onLayout={(event) => { this.getItemDimensions(event.nativeEvent.layout) }}>
<View>
<Text>{item.fulltext}</Text>
</View>
</View>
</TouchableOpacity>
);
case '1':
console.log("Dummy Case 1 FULLTEXT: " + item.fulltext);
return (
<TouchableOpacity>
<View onLayout={(event) => { this.getItemDimensions(event.nativeEvent.layout) }}>
<View>
<Text>{item.fulltext}</Text>
</View>
</View>
</TouchableOpacity>
);
case '2':
console.log("Dummy Case 2 FULLTEXT: " + item.fulltext);
return (
<TouchableOpacity>
<View onLayout={(event) => { this.getItemDimensions(event.nativeEvent.layout) }}>
<View style={{ flexDirection: 'row' }}>
<Text>{item.section}</Text>
<Text>{item.fulltext}</Text>
</View>
</View>
</TouchableOpacity>
);
default:
return (
<TouchableOpacity>
<View>
<View onLayout={(event) => { this.getItemDimensions(event.nativeEvent.layout) }}>
<Text>{item.type} {item.fulltext} </Text>
</View>
</View>
</TouchableOpacity>
);
}
} else {
console.log("Dummy Case Blank Render");
return (
<TouchableOpacity>
<View onLayout={(event) => { this.getItemDimensions(event.nativeEvent.layout) }}>
<View>
<Text> </Text>
</View>
</View>
</TouchableOpacity>
)
}
}
}
AppRegistry.registerComponent('DummyMainItem', () => DummyMainItem);
我希望我的代码在每次渲染视图时都会调用 getItemDimensions() 函数,该函数本身会调整 this.state.currentItem 的状态,这种状态变化会导致触发 render() 函数再次。
实际行为是它执行上述操作,但次数有限(比我需要的 18000 更接近 10 次)。 onLayout 不会调用 getItemDimensions(),因此不会获得尺寸,并且 currentItem 的状态不会得到高级 - 因此渲染停止。我不明白为什么对于屏幕上显示的最后一个视图,onLayout 没有调用 getItemDimensions。
是否有人对迭代停止的原因或实现目标的更有效方法有任何见解?我需要向我的 FlatList 提供 getItemLayout,因为在用户手动滚动整个 FlatList 之前,应用程序需要能够 ScrollToIndex。
【问题讨论】:
标签: react-native react-native-flatlist