【发布时间】:2020-11-16 06:49:28
【问题描述】:
说明
我正在实现一个图像选择器,但有一些我需要解决的性能问题... 在我的组件中,用户可以从他的画廊中选择多个项目(图像)(FlatList 呈现他画廊中的所有图像)。当某个项目被选中时,它被添加到所选图像的数组中(它是一个状态)。
问题
由于数组是有状态的,组件将重新渲染...但我只需要重新渲染用户单击的图像(因为其中会显示一个徽章)而不是完整的 FlatList。
任何想法如何做到这一点?
代码
const keyExtractor = ({ uri }) => uri;
class ImagePicker extends React.Component {
static propTypes = {
...
};
loading = false;
cursor = null;
state = {
images: [],
pickedImages: [], // <----------------------------------
};
componentDidMount() {
this.getImages();
}
getImages = async (after) => {
if (this.loading) return;
this.loading = true;
const results = await MediaLibrary.getAssetsAsync({
first: 20,
after,
sortBy: MediaLibrary.SortBy.creationTime,
});
const { assets, hasNextPage, endCursor } = results;
this.setState({ images: this.state.images.concat(assets) }, () => {
this.loading = false;
this.cursor = hasNextPage ? endCursor : null;
});
};
getNextImages = () => {
// If there are no more pics to get, do nothing
if (!this.cursor) return;
/*
If we don't check the above condition,
once we reach the final of the camera roll,
the beginning will be loaded again
*/
this.getImages(this.cursor);
};
pickImage = (image) => {
/*
This method returns a boolean that indicates
if it was possible to select the image tapped by the user
*/
const { pickedImages } = this.state;
// If the element is already in the list remove it
if (isElementInList(image, pickedImages)) {
this.setState({
pickedImages: removeListElement(image, pickedImages),
});
return false;
}
// Do nothing if the user has already selected MAX_ALBUM_LENGTH images
if (pickedImages.length === MAX_ALBUM_LENGTH) return false;
// If the image is not currently picked, add it to the list of picked images
if (!isElementInList(image, pickedImages)) {
this.setState({
pickedImages: [...pickedImages, image], // <----------------------------------------
});
return true;
}
};
renderItem = ({ item: { uri }, size, marginTop, marginLeft }) => {
const style = {
width: size,
height: size,
marginLeft,
marginTop,
};
const { pickedImages } = this.state;
return (
<Item
uri={uri}
onPress={this.pickImage}
pickedImages={pickedImages}
style={style}
/>
);
};
render() {
const {
theme: { colors },
handleClose,
handleConfirm,
} = this.props;
const { images, pickedImages } = this.state;
return (
<>
<View style={styles.topButtonsContainer}>
<TouchableOpacity
activeOpacity={0.5}
style={styles.topButton}
onPress={handleClose}
>
<Icon
name="ios-close"
type="ionicon"
color={colors.black}
size={40}
/>
</TouchableOpacity>
{pickedImages.length > 0 && (
<TouchableOpacity
activeOpacity={0.5}
style={styles.topButton}
onPress={handleConfirm}
>
<Icon
name="ios-checkmark"
type="ionicon"
color={colors.black}
size={40}
/>
</TouchableOpacity>
)}
</View>
<Grid
data={images}
keyExtractor={keyExtractor}
renderItem={this.renderItem}
initialNumToRender={20}
removeClippedSubviews
onEndReached={this.getNextImages}
/>
</>
);
}
}
Pd:组件“Grid”只是一个 FlatList 包装器
【问题讨论】:
标签: javascript reactjs react-native ecmascript-6 expo