我测试FlatList。这是我想做的:
1.使用componentDidmount
获得10个初始数据
2.向下滚动以获取更多10个数据
App.js
import React from 'react';
import {
View,
SafeAreaView,
Text,
FlatList,
} from 'react-native';
import throttle from 'lodash.throttle';
import { tmpPosts } from './src/data/tmpdata';
class App extends React.Component {
constructor(props) {
super(props);
this.page = 0;
this.state = {
posts: [],
};
this.getMoreDataThrottled = throttle(this.getMoreData, 3000);
}
componentDidMount() {
console.log('comoponentDidMount')
this.getMoreDataThrottled();
}
componentWillUnmount() {
this.getMoreDataThrottled.cancel();
}
getMoreData = () => {
console.log('start getMoreData')
const tmpList = []
for (let i = 0; i < 10; i++ ) {
tmpList.push(tmpPosts[this.page])
this.page += 1;
}
this.setState(prevState => ({
posts: prevState.posts.concat(tmpList)
}));
}
renderPost = ({item}) => {
console.log(item.id)
return (
<View style={{height: 200}}>
<Text>{item.id}</Text>
</View>
);
};
render() {
return (
<SafeAreaView>
<FlatList
data={this.state.posts}
renderItem={this.renderPost}
keyExtractor={post => String(post.id)}
initialNumToRender={10}
onEndReachedThreshold={0.01}
onEndReached={this.getMoreDataThrottled}
/>
</SafeAreaView>
);
}
}
export default App;
tmpdata.js
let num = 0;
export const tmpPosts = [
{id: String(num += 1)},
{id: String(num += 1)},
.
.
.
]
我实现了我想要的,但是渲染发生了很多。
这是console.log
comoponentDidMount
start getMoreData
1
2
3
.
.
.
8
9
10
1
2
3
.
.
.
8
9
10
start getMoreData
1
2
3
.
.
.
8
9
10
1
2
3
.
.
.
18
19
20
start getMoreData
1
2
3
.
.
.
18
19
20
1
2
3
.
.
.
28
29
30
日志似乎表示:
1.每次重新渲染两次。
2. FlatList渲染数增加,因为它也渲染旧数据。
我检查了类似的问题,这似乎是FlatList的正常行为。
FlatList renderItem is called multiple times
FlatList calling twice
https://github.com/facebook/react-native/issues/14528
但是,恐怕当数据达到100多个时,该应用程序将运行缓慢并崩溃。
FlatList性能的最佳解决方案是什么?
ComponentUpdate是否应防止不必要的重新渲染,例如已经渲染的旧数据?
答案 0 :(得分:0)
更新
对不起,我的回答不完整。我转载了您的问题,并通过将“ Post”组件移到了单独的文件中来解决了该问题。 这篇文章扩展了pureComponent,因此如果其props没有更改,它将不会重新呈现。
class App extends React.Component {
constructor(props) {
super(props);
this.page = 0;
this.state = {
posts: []
};
this.getMoreDataThrottled = throttle(this.getMoreData, 3000);
}
componentDidMount() {
console.log("comoponentDidMount");
this.getMoreData();
}
componentWillUnmount() {
this.getMoreDataThrottled.cancel();
}
getMoreData = () => {
console.log("start getMoreData");
const tmpList = [];
for (let i = 0; i < 10; i++) {
tmpList.push(tmpPosts[this.page]);
this.page += 1;
}
this.setState(prevState => ({
posts: prevState.posts.concat(tmpList)
}));
};
renderPost = ({ item }) => {
return <Post item={item} />;
};
render() {
return (
<SafeAreaView>
<FlatList
data={this.state.posts}
renderItem={this.renderPost}
keyExtractor={post => String(post.id)}
initialNumToRender={10}
onEndReachedThreshold={0.5}
onEndReached={this.getMoreData}
/>
</SafeAreaView>
);
}
}
/*
In a separate file
*/
class Post extends React.PureComponent {
render() {
const { item } = this.props;
console.log(item.id);
return (
<View key={item.id} style={{ height: 200 }}>
<Text>{item.id}</Text>
</View>
);
}
}
// Same but in functional (my preference)
const _PostItem =({ item }) => {
console.log(item.id);
return (
<View key={item.id} style={{ height: 200 }}>
<Text>{item.id}</Text>
</View>
);
};
export const PostFunctionalWay = React.memo(_PostItem);
export default App;
原始答案
我认为您忘了在道具列表中添加道具“ extraData”:
<FlatList
data={this.state.posts}
extraData={this.state.posts}
renderItem={this.renderPost}
keyExtractor={post => String(post.id)}
initialNumToRender={10}
onEndReachedThreshold={0.01}
onEndReached={this.getMoreDataThrottled}
/>
https://facebook.github.io/react-native/docs/flatlist#extradata
PS:也许可以扩展PureComponent
PS2:您需要您的渲染项目(renderPost)具有带有唯一键的道具“ id”
renderPost = ({item}) => {
console.log(item.id)
return (
<View id={item.id} style={{height: 200}}>
<Text>{item.id}</Text>
</View>
);
};
答案 1 :(得分:-9)