Zahir Masoodi
Zahir Masoodi

Reputation: 858

Skeleton Component in React Native with react-native-reanimated

I am following a YT lecture to create a Skeleton.

But it's throwing an error undefined is not a function (near '..._reactNativeReanimated.default.sequence...')

react-native : 0.70.5

react-native-reanimated: 2.12.0


import { useEffect, useRef } from "react";
import { StyleSheet } from "react-native";
import Animated from "react-native-reanimated";

const Skeleton = () => {
    const opacity = useRef(new Animated.Value(0.3));

    useEffect(() => {
        Animated.sequence([
            Animated.timing(opacity.current, {
                toValue: 1,
                useNativeDriver: true,
                duration: 500,
            }),
            Animated.timing(opacity.current, {
                toValue: 0.3,
                useNativeDriver: true,
                duration: 800,
            }),
        ]).start();
    }, [opacity]);

    return (
        <Animated.View
            style={[
                styles.skeleton,
                { opacity: opacity.current, height: 100, width: 100 },
            ]}
        />
    );
};

const styles = StyleSheet.create({
    skeleton: {
        backgroundColor: "red",
    },
});

export default Skeleton;

Can we animate expo-linear-gradient ?

Upvotes: 1

Views: 2097

Answers (2)

Farzin
Farzin

Reputation: 495

You can use withTiming, withSequence and withRepeat to achieve what you need. (Reanimated v2)

import { useEffect } from 'react'
import { StyleSheet } from 'react-native'

import Animated, {
  withTiming,
  withRepeat,
  withSequence,
  useSharedValue,
  useAnimatedStyle
} from 'react-native-reanimated'

import theme from '@/theme'

const Skeleton = () => {
  const opacity = useSharedValue(1)

  useEffect(() => {
    opacity.value = withRepeat(
      withSequence(
        withTiming(0.3, {
          duration: 1000
        }),
        withTiming(1, {
          duration: 1000
        })
      ),
      Infinity,
      true
    )
  }, [])

  const animatedStyle = useAnimatedStyle(() => {
    return {
      opacity: opacity.value
    }
  })

  return <Animated.View style={[styles.skeleton, animatedStyle]} />
}

const styles = StyleSheet.create({
  skeleton: {
    backgroundColor: theme.colors.generateBlack(20),
    flex: 1
  }
})

export default Skeleton

Upvotes: 0

Animated.sequence was deprecated in version 2.. try with parallel

import { useEffect, useRef } from "react";
import { StyleSheet } from "react-native";
import Animated from "react-native-reanimated";

const Skeleton = () => {
    const opacity = useRef(new Animated.Value(0.3));

    useEffect(() => {
        Animated.parallel([
            Animated.timing(opacity.current, {
                toValue: 1,
                useNativeDriver: true,
                duration: 500,
            }),
            Animated.timing(opacity.current, {
                toValue: 0.3,
                useNativeDriver: true,
                duration: 800,
            }),
        ]).start();
    }, [opacity]);

    return (
        <Animated.View
            style={[
                styles.skeleton,
                { opacity: opacity.current, height: 100, width: 100 },
            ]}
        />
    );
};

const styles = StyleSheet.create({
    skeleton: {
        backgroundColor: "red",
    },
});

export default Skeleton;

Upvotes: 1

Related Questions