Changing from old Animated to the newer reanimated giving me problems

311 views Asked by At

I am trying to change some code that is using the old Animated within react native. The scenario is that I have a basic flatlist that has only 4 test items. When one is clicked it simply performs a basic animation on only the clicked item.

I have managed to swap it over to the new reanimated but it is not isolating the one item when clicked? I have changed the animation but this is purely because of the example given in the official code because eventually I would like to play with the selected item more.

It is sort of frustrating because I can not work out why it is animating all the items?

Here is the working code with the old Animated working :-

class Item extends Component {
  constructor() {
    super(); 
    this.state = { animation: new Animated.Value(1) };
  }

  startAnimation (){
    const animations = [
      Animated.timing(this.state.animation, {
        toValue: 1.5,
        duration: 500
      }),
      Animated.timing(this.state.animation, {
        toValue: 1,
        duration: 500
      }),
      Animated.timing(this.state.animation, {
        toValue: 2,
        duration: 500
      }),
       Animated.timing(this.state.animation, {
        toValue: 1,
        duration: 500
      }),
    ];

    Animated.sequence(animations).start()
  }

  render() {
    const { values, index } = this.props;

    return (
      <Animated.View style={{margin: 10, transform:[{scale: this.state.animation}]}}>
        <TouchableOpacity onPress={() => {this.startAnimation(); alert(index);} }>
          <Text>{values.name}</Text>
        </TouchableOpacity>
      </Animated.View>
    );
  }

}

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      items: [
        { id: 1, name: 'name 1' },
        { id: 2, name: 'name 2' },
        { id: 3, name: 'name 3' },
        { id: 4, name: 'name 4' },
      ]
    };
  }

  render() {
    return (
      <View style={styles.container}>
          <FlatList
            numColumns={4}
            data={this.state.items}
            renderItem={({item, index}) => <Item key={index} values={item} index={index} />}
          />
      </View>
    );
  }
}

and with the new reanimated version :-

const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);

const items = [
        { id: 1, name: 'name 1' },
        { id: 2, name: 'name 2' },
        { id: 3, name: 'name 3' },
        { id: 4, name: 'name 4' },
]


 
export default function App() {

const rotation = useSharedValue(0);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ rotateZ: `${rotation.value}deg` }],
  }));

  const handlePress = () => {
    rotation.value = withSequence(
      // deviate left to start from -ANGLE
      withTiming(-ANGLE, { duration: TIME / 2, easing: EASING }),
      // wobble between -ANGLE and ANGLE 7 times
      withRepeat(
        withTiming(ANGLE, {
          duration: TIME,
          easing: EASING,
        }),
        7,
        true
      ),
      // go back to 0 at the end
      withTiming(0, { duration: TIME / 2, easing: EASING })
    );
  };




const Item = ({item}) => {
     return ( 
  <View style={styles.item}>
  <Animated.View style={animatedStyle}>
    <Text onPress={handlePress} style={{margin: 10}}>{item.name}</Text>
    </Animated.View>
  </View>
     )
};

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.container}>
          <FlatList
           numColumns={4}
            data={items}
            renderItem={Item}
            keyExtractor={item => item}
          />
      </View>
    </SafeAreaView>
  );
}

I have tried adding this but it just stop everything. In the first one, the click refers to this , do I need to add this into the click?

const animatedStyle = new useAnimatedStyle(() => ({

1

There are 1 answers

0
JulesUK On

I have it working, I had to place the animation directly into the ITEM, so each ITEM has its own animate sequence. It works but something tells me there is something else I could do to reduce the amount of code?

import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, FlatList,  TouchableOpacity, SafeAreaView, Image, Pressable } from 'react-native';
import Animated, {
  useSharedValue,
  withTiming,
  Easing,
  useAnimatedStyle,
  withRepeat,
  withSequence,
} from 'react-native-reanimated';

const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);



const Item = ({ item }) => {

const rotation = useSharedValue(0);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ rotateZ: `${rotation.value}deg` }],
  }));

 const handlePress = () => {

    rotation.value = withSequence(
      // deviate left to start from -ANGLE
      withTiming(-ANGLE, { duration: TIME / 2, easing: EASING }),
      // wobble between -ANGLE and ANGLE 7 times
      withRepeat(
        withTiming(ANGLE, {
          duration: TIME,
          easing: EASING,
        }),
        7,
        true
      ),
      // go back to 0 at the end
      withTiming(0, { duration: TIME / 2, easing: EASING })
    );
  };


    return (
      <Animated.View style={animatedStyle}>
        <Pressable onPress={() => {handlePress()} }>
          <Text>{item.name}</Text>
        </Pressable>
      </Animated.View>
    );


  }






export default function App() {

const items = [
        { id: 1, name: 'name 1' },
        { id: 2, name: 'name 2' },
        { id: 3, name: 'name 3' },
        { id: 4, name: 'name 4' },
      ];

  return (
    <SafeAreaView style={styles.container}>
              <FlatList
            numColumns={4}
            data={items}
            renderItem={({item, index}) => <Item key={index} item={item} index={index} />}
          
          />

    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});