Leo S
Leo S

Reputation: 339

react animation animated component undefined

I want to create a circular animation like a wave and i found that code on the internet. And i converted and changed it with react hooks but then this code does not work correctly. Where is my mistake?

const constructAnimations = [...Array(COUNT).keys()].map(() => initialPhase);

export default function SearchAnimation() {
  const [stateAnimations, setStateAnimations] = useState(constructAnimations);

  useEffect(() => {
    const actions = Array(COUNT).fill(
      keyframes({
        values: [initialPhase, { scale: 2, opacity: 0 }],
        duration: DURATION,
        loop: Infinity,
        yoyo: Infinity,
      })
    );

    stagger(actions, DURATION / COUNT).start((animations) => {
      setStateAnimations({ animations });
    });
  }, []);

  return (
    <View style={styles.container}>
      {[stateAnimations].map(({ opacity, scale }, index) => {
        return (
          <Animated.View
            key={index}
            style={[
              styles.circle,
              {
                transform: [{ scale }],
                opacity,
              },
            ]}
          />
        );
      })}
      <View style={styles.midCircle}>
        <FontAwesome name="phone" style={styles.icon} />
        <Text style={styles.text}>Searching</Text>
      </View>
    </View>
  );
}

Also the error message:

TypeError: undefined is not an object (evaluating 'value.getValue')
This error is located at:
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at SearchAnimation.js:33)
    in RCTView (at View.js:34)

Upvotes: 0

Views: 1219

Answers (1)

bas
bas

Reputation: 15462

There are a couple of problems I've found.

The first is that the class based example you linked maps over the stateAnimations array, but you map over [stateAnimations]. So since stateAnimations is already an array you don't need to surround it with another array. If you fix this the error you posted in your question goes away.

I also found that the working class-based example uses version 8.6.2 of popmotion and the code in the example apparently doesn't work anymore for version 9+.

So after downgrading to 8.6.2 the following code worked for me:

import React, { useState, useEffect } from "react";
import { Animated, Text, View, StyleSheet } from "react-native";
import { keyframes, stagger, tween } from "popmotion";
import { FontAwesome } from "@expo/vector-icons";

const COUNT = 4;
const DURATION = 5000;
const initialPhase = { scale: 0, opacity: 1 };
const constructAnimations = [...Array(COUNT).keys()].map(() => initialPhase);

export default function SearchAnimation() {
  const [stateAnimations, setStateAnimations] = useState(constructAnimations);

  useEffect(() => {
    const actions = Array(COUNT).fill(
      keyframes({
        values: [initialPhase, { scale: 2, opacity: 0 }],
        duration: DURATION,
        loop: Infinity,
        yoyo: Infinity,
      })
    );

    stagger(actions, DURATION / COUNT).start((animations) => {
      setStateAnimations(animations);
    });
  }, []);

  return (
    <View style={styles.container}>
      {stateAnimations.map(({ opacity, scale }, index) => {
        return (
          <Animated.View
            key={index}
            style={[
              styles.circle,
              {
                transform: [{ scale }],
                opacity,
              },
            ]}
          />
        );
      })}
      <View style={styles.midCircle}>
        <FontAwesome name="phone" style={styles.icon} />
        <Text style={styles.text}>Searching</Text>
      </View>
    </View>
  );
}

const getCircle = (radius, backgroundColor = "gold") => ({
  backgroundColor,
  width: radius * 2,
  height: radius * 2,
  borderRadius: radius,
  position: "absolute",
});

const styles = StyleSheet.create({
  icon: {
    color: "white",
    fontSize: 42,
    marginBottom: 5,
  },
  text: {
    color: "white",
    fontSize: 18,
  },
  circle: getCircle(100),
  midCircle: {
    ...getCircle(75),
    alignItems: "center",
    justifyContent: "center",
  },
  container: {
    flex: 1,
    alignItems: "center",
    backgroundColor: "#fff",
    justifyContent: "center",
  },
});

Upvotes: 3

Related Questions