Search code examples
reactjsreact-nativereact-animatedlottiereact-animations

Is it possible to assign a value (id) to animations in React Native?


Say if my animation is being iterated 20 times, but I don't want all of them playing at the same time. How would I go about triggering that one specific animation that have a value of 1. If I clicked on 1 then the other 19 should not trigger except that 1.

    export default class AnimateScreen extends React.PureComponent {
    constructor(props){

      super(props);

      this.forceUpdateHandler = this.forceUpdateHandler.bind(this);

      this.state = {
      dataSource: '',
      progress: new Animated.Value(0),
    };


    animate = (id) => {

          Animated.timing(this.state.progress, {
            toValue: 1,
            duration: 5000,
            easing: Easing.linear,
          }).start([id]); <!-- Here is my attempt in trying to animate that one specific animation. 


render(){
return(
    <FlatList
               data={this.state.dataSource}
               renderItem={({item}) => 
              <View>
               <View>
                 <Text>Work in progress</Text>
                 <View>
                 <TouchableHighlight
                 onPress={this.animate.bind(this, item.id)}>
                  <Animation
                  progress={this.state.progress}
                  source={require('../tools/animations/heart_icon.json')}
                  />
        </TouchableHighlight>

                   <Text> Hello</Text>

                 </View>

               </View>


               </View>
             }
             keyExtractor={(item, index) => index.toString()}
          />
        );
        }
    }

I tried this out and still, all of the animations triggered. Is there a way to trigger them specifically?

DataSource:

"dataSource":[{"id":"10","images":"Emerson live in the sunshine swim in the sea drink the wild air.jpg","note":"Hello","tag":"sunshine"}


    componentDidUpdate(prevProps, prevState) {
  if (!prevState.dataSource) {

      return fetch(`https://www.website.com/React/json-data.php` , {
       method: 'POST',
       headers: {
         'Accept': 'application/json',
         'Content-Type': 'application/json',
       }

      })
        .then((response) => response.json())
        .then((responseJson) => {
          this.setState({
            dataSource: responseJson,
            },function() {
              // In this block you can do something with new state.
            });
        })
        .catch((error) => {
          console.error(error);
        });
    }
  }

Solution

  • Basically you can add progress key to each item in the dataSource with an animated value to 0 then on click you will animate that item's progress. It should roughly look like this:

    export default class AnimateScreen extends React.PureComponent {
      constructor(props){
    
        super(props);
    
        this.forceUpdateHandler = this.forceUpdateHandler.bind(this);
    
        this.state = {
          dataSource: [],
          progress: new Animated.Value(0),
        };
    
        componentDidUpdate(prevProps, prevState) {
          if (!prevState.dataSource) {
    
            return fetch(`https://www.website.com/React/json-data.php` , {
              method: 'POST',
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
              }
    
            })
            .then((response) => response.json())
            .then((responseJson) => {
              this.setState({
                dataSource: responseJson.map(item => ({ ...item, progress: new Animated.Value(0) })), // Add progress key
              },function() {
                // In this block you can do something with new state.
              });
            })
            .catch((error) => {
              console.error(error);
            });
          }
        }
    
    
        animate = (item) => {
          Animated.timing(item.progress, {
            toValue: 1,
            duration: 5000,
            easing: Easing.linear,
          }).start(); <!-- Here is my attempt in trying to animate that one specific animation. 
    
    
          render(){
            return(
              <FlatList
                data={this.state.dataSource}
                renderItem={({item}) => 
                <View>
                  <View>
                    <Text>Work in progress</Text>
                    <View>
                      <TouchableHighlight
                        onPress={() => this.animate(item)}>
                        <Animation
                          progress={item.progress}
                          source={require('../tools/animations/heart_icon.json')}
                        />
                      </TouchableHighlight>
    
                      <Text> Hello</Text>
    
                    </View>
    
                  </View>
    
    
                </View>
              }
              keyExtractor={(item, index) => index.toString()}
            />
          );
        }
      }