代码之家  ›  专栏  ›  技术社区  ›  Jo Momma

如何使用React防止在平面列表中重新加载图像。备忘录

  •  0
  • Jo Momma  · 技术社区  · 4 年前

    在我的Redux商店中,我保留了一个活动的报表对象。这个复杂对象有一个照片对象数组,由一个带有id字段和uri字段的对象组成。例如,报表对象可能如下所示:

    {
        title: "some title",
        date: "some date",
        ... a bunch of other data
        photos: [
           {uri: someURI, id: some id},
           {uri: someURI, id: some id},
           {uri: someURI, id: some id},
       ]
    }
    

    我将这些图像uri(不是本地文件,它们指向firestore存储)加载到一个平面列表中,如下所示:

    <FlatList
       ref={listRef}
       numColumns={3}
       columnWrapperStyle={{ marginBottom: 10 }}
       nestedScrollEnabled={true}
       showsVerticalScrollIndicator={false}
       data={activeReport?.photos}
       renderItem={renderImages}
    />
    

    然后我用这个函数调用renderItems:

    const renderImages = ({ item, index }) => {
          const screenWidth = ((Dimensions.get('window').width - 50) / 3)
          const marginH = (index + 2) % 3 === 0 ? 10 : 0
    
          return (
             <AsyncImage
                image={item}
                    key={item.id}
                onPress={() => navigation.navigate('Photo', { image: item })}
                containerStyles={{ width: screenWidth, alignItems: 'center'}}
                onLongPress={() => {
                   Alert.alert('Delete Photo?', 'Are you sure you want to delete this photo?', [
                      {
                         text: 'Cancel',
                         style: 'cancel',
                      },
                      {
                         text: 'Delete',
                         onPress: () => {
                            _deleteImageAsync(item)
                         },
                         style: 'destructive',
                      },
                   ])
                }}
             />
          )
       }
    

    最后,这里是我的AsyncImage组件代码:

    function AsyncImage({ imageStyles = {}, image, onPress, onLongPress, containerStyles }) {
       const [loading, setLoading] = useState(true)
    
       return (
          <TouchableOpacity
             key={image.id}
             activeOpacity={0.7}
             onPress={onPress}
             onLongPress={onLongPress}
             style={[styles.touchableWrapper, containerStyles]}>
    
             <ImageBackground
                source={require('../../../../assets/image.png')}
                resizeMode='cover'
                style={[styles.image, styles.placeholderImage]}
             />
    
             <Image
                style={[styles.image, imageStyles]}
                source={{ uri: image.uri }}
                resizeMode='cover'
                onLoadEnd={() => {
                   setLoading(false)
                }}
             />
    
             {loading && (
                <>
                   <ActivityIndicator animating={true} size={36} color={colors.colorPrimary} style={styles.indicator} />
                </>
             )}
          </TouchableOpacity>
       )
    }
    
    const areEqual = (prevProps, nextProps) => {
       const { image } = nextProps
       const { image: prevImage } = prevProps
       return image.uri === prevImage.uri
    }
    
    const styles = StyleSheet.create({
       touchableWrapper: {
          borderRadius: 5,
          overflow: 'hidden',
          marginHorizontal: 5,
       },
       image: {
          backgroundColor: colors.colorCharcoalDark,
          resizeMode: 'cover',
          width: '100%',
          aspectRatio: 1,
          borderColor: colors.colorGrayDark,
          borderWidth: 0.5,
          borderRadius: 5,
       },
       placeholderImage: {
          position: 'absolute',
          top: 0,
          bottom: 0,
          left: 0,
          right: 0,
       },
       indicator: {
          position: 'absolute',
          top: 0,
          bottom: 0,
          left: 0,
          right: 0,
       },
    })
    
    export default React.memo(AsyncImage, areEqual)
    

    以下是我的删除照片功能:

    const _deleteImageAsync = async (photo) => {
          if (!photo) return
          try {
             // delete image from report in firestore
             const reportRef = db.collection('reports').doc(activeReport.reportID)
             const report = (await reportRef.get()).data()
                
             // make sure photo exists before trying to remove it from firestore
             if (report.photos.some((p) => p.id === photo.id)) {
                reportRef.update({
                   photos: firebase.firestore.FieldValue.arrayRemove(photo),
                })
             } else {
                    throw new Error('Could not delete photo. Please try again')
                }
             // delete photo from storage
             const ref = storage.ref(activeReport?.reportID).child(photo.id)
             await ref.delete()
    
                dispatch(removeReportPhoto(photo))
    
          } catch (error) {
                // todo: handle error here
             console.log('Delete photo: ', error.message)
             alert('was not able to delete photo from cloud storage.')
          }
       }
    

    问题

    当我在阵列中添加一张新照片时,一切都很好。然而,当我从数组中删除一个元素时,尽管我使用了React,但仍会重新加载一些(但不是全部)图像。备忘录

    我花了数小时和数天的时间试图找出原因。我迷路了。我想在这个问题上得到一些帮助

    如果有人需要查看我的代码,请告诉我,但这对我来说非常直接

    0 回复  |  直到 4 年前
    推荐文章