0

I am creating an app and experimenting with components and most of all, animations. I have the below code with two class components:

import * as React from 'react';
import { StyleSheet, Text, View,  TouchableOpacity, Image, ImageBackground, Animated, Easing, Platform
} from 'react-native';
import { frame1 } from '../master-new/assets/index';
import { frame2 } from '../master-new/assets/index';
import { frame3 } from '../master-new/assets/index';

import { background } from '../master-new/assets/index';

const Images= [
  { id: 1, src: frame1, title: 'foo', description: 'bar'},
  { id: 2, src: frame2, title: 'foo', description: 'bar'},

]

const length = Images.length;

class Animation extends React.Component {
  constructor(){
  super();
  this.animations = new Animated.Value(0);
  this.opacity = [];
  Images.map((item, index) => {
    this.opacity.push(
      this.animations.interpolate({
        inputRange: [index - 1, index, index + 1],
        outputRange: [0, 1, 0],
      }),
    );
  });
 }
  componentDidMount() {
    Animated.loop(
      Animated.timing(this.animations, {
        toValue: length - 1,
        duration: 2000 * length,
        easing: Easing.linear,
        useNativeDriver: true,
      }),
    ).start();
  }

  render() {

    return(
      <View style={styles.container}>

          {Images.map((item, index) => {
          const opacity = this.opacity[index];
          return (
            <Animated.View
              style={[styles.anim, {frame: item, opacity}]}
            />
          );
        })}

      </View>
    )
  }
}

export default class Timer extends React.Component {
  constructor(props){
  super(props);

  this.state = {
    time:0,
    start:0,
    isOn:false, 
    submit:false,
    scoreArray: [],
    animalArray: [],
    fadeAnim: new Animated.Value(0),

    pauseOver: false,
    pauseToggle: 'up',

  }

}

sampleInfo = [
  {
  second: 1,
  ml: '19ml',
  animal: 'Thing1',
  weight: '4kg',
  capacity: '20ml'
  },

  {
  second: 2,
  ml: '38ml',
  animal: 'Thing2',
  weight: '7kg',
  capacity: '35ml'
  },

  {
  second: 3,
  ml: '57ml',
  animal: 'Thing3',
  weight: '12kg',
  capacity: '60ml'
  }

] 

  render() {

    return(
      <View style={styles.container}>

      <Animation />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: "column"
  },
  background: {
    flex: 1,
    resizeMode: "cover",
    justifyContent: "center"
  },
  anim: {
    flex: 1,
    width: '100%'

    }

});

I'm displaying with expo and have successfully displayed apps before and tested them in action. Can someone tell me why I'm seeing just a blank screen for this one?

I'm getting a warning saying Each chile in a list should have a unique key prop. Check the render method of animation, so I guess that's where the issue lies but why and is it the cause of just a white screen?

I've read: Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`

and:

https://reactjs.org/docs/lists-and-keys.html

but it didn't clear anything up for me!

T

NightTom
  • 418
  • 15
  • 37

2 Answers2

0

react need a way to identify the nodes inside the UI, when you render a list/array, you need to provide the key attribute to the component, in your case it is when you render the images array, that is when react complains about that, react needs this to know what item to update if an update in the state was made.

to slove this issue, simply add the key attribuite to the component, make sure the value is unique, either an id or the index of the item


 render() {

    return(
      <View style={styles.container}>

          {Images.map((item, index) => {
          const opacity = this.opacity[index];
          return (
            <Animated.View
              key = {item.id}
              style={[styles.anim, {frame: item, opacity}]}
            />
          );
        })}

      </View>
    )
  }

PS: only use index as a last resort, in your case you have ids, which is guaranteed to be unique, index however, is not guaranteed.

Ahmed Khattab
  • 2,645
  • 2
  • 13
  • 19
0

You need to put key attributes on the JSX elements returned in a loop. Like:

{Images.map((item, index) => {
  const opacity = this.opacity[index];
  return (
    <Animated.View
      key={index}
      style={[styles.anim, {frame: item, opacity}]}
    />
  );
})}
bmovement
  • 827
  • 7
  • 11
  • That's removed the warning, but the screen remains blank. I can display an image, but the code I have for the animation is just not working. – NightTom May 27 '20 at 08:09