DEV Community

Cover image for React Native Skeleton Loader Componen
Akash Yadav
Akash Yadav

Posted on

4

React Native Skeleton Loader Componen

This is a reusable React Native component for rendering skeleton loaders with customizable dimensions and animations. Skeleton loaders are placeholders used to provide a better user experience while loading content in an application. The component supports both animated and static skeletons, and it can measure the dimensions of a child component to render skeletons with the same dimensions. This component can be useful for improving the perceived performance of your React Native application.

Image description

Image description

Image description

Image description

Image description

Image description



import { useState } from "react";
import { Dimensions, View, Text, Platform } from "react-native"
import LinearGradient from "react-native-linear-gradient";
import colors from "../utils/constant/colors";
import Animated, { useAnimatedProps, useFrameCallback, useSharedValue, withTiming } from "react-native-reanimated";

interface SkeltonContainerProps {
    child: any;
    childcount?: any;
    width?: any;
    height?: any;
}

interface SkeletonProps {
    width: number;
    height: number;
    marginTop?: number;
}

const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient);

const SkeletonAnimated = ({ width, height, marginTop }: SkeletonProps) => {
    const locationY = useSharedValue(0);

    useFrameCallback(() => {
        if (locationY.value == 1) locationY.value = withTiming(0, { duration: 1000 });
        if (locationY.value == 0) locationY.value = withTiming(1, { duration: 1000 });
    });

    const animatedProps = useAnimatedProps(() => {
        return { locations: [0, locationY.value] }
    })

    return (
        <AnimatedLinearGradient colors={[colors.LightGray, colors.White]} animatedProps={animatedProps} style={{ width: width, height: height, marginTop: marginTop }} />
    )
}

const SkeletonStatic = ({ width, height, marginTop }: SkeletonProps) => {
    return (
        <LinearGradient colors={[colors.LightGray, colors.White]} style={{ width: width, height: height, marginTop: marginTop }} />
    )
}

const Skeleton = ({ width = Dimensions.get('window').width, height = 200, marginTop = 0 }: SkeletonProps) => {
    return (
        Platform.OS == 'ios' ?
            <SkeletonAnimated width={width} height={height} marginTop={marginTop} /> :
            <SkeletonStatic width={width} height={height} marginTop={marginTop} />
    )
}


const SkeletonContainer = ({ child, childcount = 1, width = Dimensions.get('window').width, height = 64 }: SkeltonContainerProps) => {
    const [dimensions, setDimensions] = useState({ width: 0, height: 0 })
    return (
        child ?
            <View>
                <View style={{ opacity: 0 }} onLayout={(event) => setDimensions({ width: event.nativeEvent.layout.width, height: event.nativeEvent.layout.height })}>{child}</View>
                <Skeleton width={dimensions.width} height={dimensions.height} marginTop={-dimensions.height} />
                {[...Array(childcount - 1).keys()].map((index) => <Skeleton key={index} width={dimensions.width} height={dimensions.height} />)}
            </View> :
            [...Array(childcount).keys()].map((index) => <Skeleton key={index} width={width} height={height} />)
    )
}

export default SkeletonContainer;


Enter fullscreen mode Exit fullscreen mode

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay