Skip to content

Instantly share code, notes, and snippets.

@dilipsuthar97
Created February 27, 2025 10:25
Show Gist options
  • Save dilipsuthar97/da1cab10de2dd8cb39cafd9dff5f1f91 to your computer and use it in GitHub Desktop.
Save dilipsuthar97/da1cab10de2dd8cb39cafd9dff5f1f91 to your computer and use it in GitHub Desktop.
Custom image view component with image loading loader and placeholder
import React, { memo, useCallback } from 'react';
import {
ActivityIndicator,
ImageResizeMode,
ImageSourcePropType,
ImageStyle,
StyleProp,
StyleSheet,
View,
} from 'react-native';
import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { Colors, Images } from '../../CommonConfig';
interface ImageViewProps {
key?: string;
style: StyleProp<ImageStyle>;
source: ImageSourcePropType;
resizeMode?: ImageResizeMode;
showLoader?: boolean;
showLoaderWithImage?: boolean;
onImageLoad?(): void;
}
const ImageView: React.FC<ImageViewProps> = ({
key,
style,
source,
resizeMode = 'cover',
showLoader,
showLoaderWithImage,
onImageLoad,
}) => {
const opacity = useSharedValue(1);
const onLoad = useCallback(() => {
opacity.value = withTiming(0, { duration: 250 }, finished => {
if (finished && onImageLoad) {
runOnJS(onImageLoad)();
}
});
}, []);
const onError = useCallback(() => {
opacity.value = withTiming(1, { duration: 250 });
}, []);
const rePlaceholder = useAnimatedStyle(() => {
return {
opacity: opacity.value,
};
});
return (
<View>
<Animated.Image
resizeMode={resizeMode}
key={key}
style={[styles.image, style]}
source={source}
onLoad={onLoad}
onError={onError}
/>
{showLoader || showLoaderWithImage ? (
<Animated.View style={[styles.center, rePlaceholder]}>
<ActivityIndicator color={Colors.PRIMARY} size={'large'} />
{showLoaderWithImage && (
<Animated.Image
resizeMode={'contain'}
key={key}
style={[rePlaceholder, style, { position: 'absolute' }]}
source={Images.PLACEHOLDER}
/>
)}
</Animated.View>
) : (
<Animated.Image
resizeMode={'contain'}
key={key}
style={[rePlaceholder, style]}
source={Images.PLACEHOLDER}
/>
)}
</View>
);
};
export default memo(ImageView);
const styles = StyleSheet.create({
image: {
position: 'absolute',
},
center: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignContent: 'center',
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment