关于同一问题,我发现了许多问题,但似乎都无法解决问题。目前,我正在使用redux来获取对象数组,操纵该数据以匹配SectionList数据要求,并将其馈送到SectionList section属性。在RenderItem中,我使用FlatList并提供道具propsections.data。最后,FLatList中的renderItem是PureComponent。我已经尝试过使用shouldComponentUpdate和其他人建议的针对节列表的其他道具,但似乎无济于事。 SectionList始终将项目渲染3次或更多次。这是我的代码:
// SECTION LIST COMPONENT
import React, { Component } from 'react';
import {
View,
SectionList,
ActivityIndicator,
Text,
AsyncStorage,
} from 'react-native';
import { connect } from 'react-redux';
import { getReleases } from '#modules/Collection/actions';
import { Header, SectionFlatList } from '#common/';
class UserCollections extends Component {
static navigationOptions = {
header: null,
};
state = {
records: [],
refreshing: false,
userData: {},
page: 1,
};
componentDidMount() {
this.getUserCollection();
}
getUserCollection = async () => {
const token = await AsyncStorage.getItem('access_token');
const tokenSecret = await AsyncStorage.getItem('access_token');
const user = await AsyncStorage.getItem('userMeta');
const userMeta = JSON.parse(user);
const { username } = userMeta;
const { page } = this.state;
const folder = 0;
const accessData = {
token,
tokenSecret,
};
try {
await this.props.dispatch(
getReleases(accessData, username, folder, page)
);
} catch (error) {
console.log('ERROR', error);
}
};
handleRefresh = () => {
this.setState(
{
page: 1,
seed: this.state.seed + 1,
refreshing: true,
},
() => {
this.getUserCollection();
this.setState({ refeshing: false });
}
);
};
handleLoadMore = () => {
this.setState(
{
page: this.state.page + 1,
},
() => {
this.getUserCollection();
}
);
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderColor: '#CED0CE',
}}
>
<ActivityIndicator animating size="large" />
</View>
);
};
_sectionKeyExtractor = (section, index) => 'S' + index.toString();
_renderSections = ({ section }) => (
<SectionFlatList {...this.props} section={section} />
);
render() {
const { releases } = this.props;
return (
<View style={styles.mainContainer}>
<View style={styles.headerContainer}>
<Header headerText={'Collection'} />
</View>
<View style={styles.contentContainer}>
<SectionList
sections={releases}
extraData={releases}
renderItem={this._renderSections}
renderSectionHeader={({ section: { title } }) => (
<Text style={{ fontWeight: 'bold', color: '#fff' }}>{title}</Text>
)}
keyExtractor={this._sectionKeyExtractor}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
/>
</View>
</View>
);
}
}
const styles = {
textContainer: {
paddingBottom: 50,
},
contentContainer: {
flex: 1,
backgroundColor: '#000',
alignItems: 'center',
justifyContent: 'space-around',
},
contentContainerStyle: {
flexDirection: 'column',
},
mainContainer: {
flex: 1,
},
};
mapStateToProps = state => {
console.log('MAP STATE TO PROPAS STATE', state);
return {
releases: state.UserCollection.releases,
};
};
export default connect(mapStateToProps)(UserCollections);
// SECTIONLIST RENDERITEM COMPONENT (FLATLIST)
import React, { PureComponent } from 'react';
import { FlatList, View } from 'react-native';
import { isEqual } from 'lodash';
import { RecordItem } from './';
class SectionFlatList extends PureComponent {
listKey = (item, index) => 'D' + index.toString();
render() {
const {
section,
navigation,
screenProps: {
user: {
accessData: { userMeta },
},
},
} = this.props;
return (
<View style={{ flex: 1 }}>
<FlatList
data={section.data}
renderItem={({ item }) => (
<RecordItem
item={item}
navigation={navigation}
userMeta={userMeta}
/>
)}
keyExtractor={this.listKey}
ListFooterComponent={this.renderFooter}
contentContainerStyle={styles.contentContainerStyle}
numColumns={3}
maxToRenderPerBatch={11}
initialNumToRender={11}
removeClippedSubviews={false}
/>
</View>
);
}
}
const styles = {
contentContainerStyle: {
flexDirection: 'column',
},
};
export { SectionFlatList };
import React, { PureComponent } from 'react';
import { TouchableOpacity, View, Image } from 'react-native';
class RecordItem extends PureComponent {
// shouldComponentUpdate(nextProps, nextState) {
// if (this.props.item.instance_id === nextProps.item.instance_id)
// return false;
// }
render() {
const { item } = this.props;
return (
<View>
<TouchableOpacity
key={item.instance_id}
onPress={() => {
navigation.navigate('AlbumDetail', {
item: item,
inCollection: true,
inWantlist: false,
userData: userMeta,
});
}}
>
<Image
style={styles.albumCovers}
source={{ uri: item.basic_information.cover_image }}
/>
</TouchableOpacity>
</View>
);
}
}
const styles = {
albumCovers: {
height: 124,
width: 124,
marginLeft: 0.5,
marginRight: 0.5,
marginTop: 0.5,
marginBottom: 0.5,
},
};
export { RecordItem };
答案 0 :(得分:0)
我有类似的问题。我没有使用redux,所以我的代码与您需要的代码不完全相同。我认为您有两种不同的原因都可能导致这种情况。
在调用onEndReached时调用这样的内容
_onEndList = () => {
if(this.state.showFooter === false && this.state.stuff.length > 0){
//console.log('getting end list');
this.AddMoreStuff();
}else{
//console.log('waiting end list');
this.waitingForMoreData();
}
}
然后,等待waitingForMoreData看起来像这样
waitingForMoreData(){
setTimeout(() => {
if(this.state.showFooter === false && this.state.stuff.length > 0){
//console.log('getting after waiting end list');
this.AddMoreStuff();
}else{
//console.log('waiting again end list');
this.waitingForMoreData();
}
}, 15000)
}
AddMoreStuff在执行其他任何操作之前将showFooter设置为true,并在进行其他所有操作后将showFooter设置为false。这些函数正在检查以确保stuff.length> 0,以便在您初次访问页面时不会与列表的初始填充同时被调用。我正在使用其他功能来做到这一点。我使用setTimeout而不是告诉它不要调用AddMoreStuff,因为如果上次调用列表时未更新列表,则FlatList有时会停止调用onEndReached。我希望这对我有帮助,即使我没有使用redux。