UNPKG

react-native-ui-lib

Version:

[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://stand-with-ukraine.pp.ua)

70 lines (69 loc) 2.42 kB
// TODO: consider unify this component functionality with our Image component import React, { useState, useCallback, useMemo } from 'react'; import { StyleSheet } from 'react-native'; import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated'; import View from "../../components/view"; import Image from "../../components/image"; import { useDidUpdate } from "../../hooks"; const UIAnimatedImage = Animated.createAnimatedComponent(Image); /** * @description: Image component that fades-in the image with animation once it's loaded * @extends: Animated.Image * @gif: https://media.giphy.com/media/l0HU7jj0ivEFyZIA0/giphy.gif * @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/AnimatedImageScreen.js */ const AnimatedImage = props => { const { containerStyle, source, loader, style, onLoad: propsOnLoad, onLoadStart: propsOnLoadStart, animationDuration = 300, testID, ...others } = props; const [isLoading, setIsLoading] = useState(false); const opacity = useSharedValue(0); useDidUpdate(() => { if (!loader) { opacity.value = 1; } }, [loader]); const onLoad = useCallback(event => { setIsLoading(false); propsOnLoad?.(event); // did not start the animation already if (opacity.value === 0) { opacity.value = withTiming(1, { duration: animationDuration }); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [setIsLoading, propsOnLoad, animationDuration]); const onLoadStart = useCallback(() => { setIsLoading(true); propsOnLoadStart?.(); }, [setIsLoading, propsOnLoadStart, animationDuration]); const fadeInStyle = useAnimatedStyle(() => { return { opacity: opacity.value }; }); // eslint-disable-next-line react-hooks/exhaustive-deps const _style = useMemo(() => [style, fadeInStyle], [style]); return <View style={containerStyle}> <UIAnimatedImage {...others} style={_style} source={source} onLoad={onLoad} onLoadStart={onLoadStart} testID={testID} imageStyle={undefined} /> {isLoading && loader && <View style={styles.loader}>{loader}</View>} </View>; }; AnimatedImage.displayName = 'AnimatedImage'; export default AnimatedImage; const styles = StyleSheet.create({ loader: { ...StyleSheet.absoluteFillObject, justifyContent: 'center' } });