import React, { useState } from 'react'; import type { ImageErrorEventData, ImageLoadEventData, ImageStyle, NativeSyntheticEvent, StyleProp, ViewStyle, } from 'react-native'; import { ActivityIndicator, Animated, ImageProps, StyleSheet, View, } from 'react-native'; import { useAnimation } from './useAnimation'; import { Image } from 'react-native'; export interface AnimatedImageProps extends Omit { fadeInDuration?: number; imageStyle?: StyleProp; containerStyle?: StyleProp; activityIndicatorProps?: React.ComponentProps; customLoadingComponent?: React.ReactNode; missingImageStyle?: StyleProp; customMissingImageComponent?: React.ReactNode; } interface AnimatedImageState { isLoading: boolean; isError: boolean; } export const AnimatedImage = (props: AnimatedImageProps) => { const { fadeInDuration = 300, imageStyle, onLoad, onError, containerStyle, activityIndicatorProps, customLoadingComponent, missingImageStyle, customMissingImageComponent, ...rest } = props; const { fadeIn, opacity } = useAnimation(); const [state, setState] = useState({ isError: false, isLoading: true, }); const handleLoadEvent = (event: NativeSyntheticEvent) => { setState({ isError: false, isLoading: false }); fadeIn({ duration: fadeInDuration }); onLoad?.(event); }; const handleErrorEvent = ( event: NativeSyntheticEvent ) => { setState({ isError: true, isLoading: false }); onError?.(event); }; return ( {state.isLoading && ( <> {customLoadingComponent ? ( <>{customLoadingComponent} ) : ( )} )} {state.isError && ( <> {customMissingImageComponent ? ( <> {customMissingImageComponent} ) : ( )} )} ); }; const styles = StyleSheet.create({ container: { justifyContent: 'center', alignItems: 'center', }, activityIndicator: { position: 'absolute', }, image: { width: 100, height: 100, }, missingImage: { width: 50, height: 50, tintColor: 'grey', }, });