react native render list of component in sequence with delay?

Viewed 22

I have an array of data which each will map to a component suppose it has 3 elements like so:

const arr = [
    {
      id: 1,
      storeName: 'papa jones besiktas',
    },
    {
      id: 2,
      storeName: 'levent store',
    },
     {
       id: 3,
       storeName: 'sariyer store',
     },
  ];

I need a way to render each element in a View with an amount of time to stay in and after that show second element, also consider each element has an animation and I need to achieve this in a very smooth way that doesn't seem that element 2 is replacing with element 1. it just smoothly enter the screen and previous element goes off the screen. I already handled animation thing but what I need is that achieve a smooth way of rendering. how can I do this in react native?

 const [curr, setCurr] = useState(0);
  const [listData, setListData] = useState([
    {
      id: 1,
      storeName: 'papa jones besiktas',
    },
    {
      id: 2,
      storeName: 'levent store',
    },
     {
       id: 3,
       storeName: 'sariyer store',
     },
  ]);
  const [renderComponentsList, setRenderComponentsList] = useState([]);

  const {colors} = useTheme();
  let bounceLittleItem = useRef(new Animated.Value(-80)).current;
  let bounceBigItem = useRef(new Animated.Value(-100)).current;

  let scaleUp = useRef(new Animated.Value(0.5)).current;

  const styles = useMemo(
    () =>
      StyleSheet.create({
        mainContainer: {
          backgroundColor: colors.CONTRAST_PRIMARY,
          height: 100,
          borderRadius: 30,
          marginHorizontal: `${(100 - GUTTERS.SCREEN_WIDTH_IN_NUMBER) / 2}%`,
          flexDirection: 'column',
          alignItems: 'flex-start',
          justifyContent: 'center',
          paddingHorizontal: 15,
          marginTop: 25,
          overflow: 'hidden',
        },
        orderContainer: {
          flexDirection: 'row',
          alignItems: 'center',
          justifyContent: 'flex-start',
        },
        storeImage: {
          width: 45,
          height: 45,
          backgroundColor: 'yellow',
          borderRadius: 40,
          marginRight: 20,
        },
        orderStatusText: {
          color: '#fff',
          fontFamily: 'BalooPaaji2-SemiBold',
        },
        storeContainer: {
          backgroundColor: '#fff',
          paddingHorizontal: 10,
          paddingVertical: 5,
          borderRadius: 20,
        },
        storeOneBeforeLastImage: {
          width: 25,
          height: 25,
          backgroundColor: 'yellow',
          borderRadius: 40,
          // marginRight: 20,
          opacity: 0.5,
        },
      }),
    [colors],
  );

  useEffect(() => {
    const inter = setInterval(() => {
      let i = 1;
      setCurr((prev) => (prev + i > listData.length - 1 ? 0 : prev + i));
      const found = listData.find((el, index) => index === curr);
      setRenderComponentsList((prevState) => [...prevState, found]);
      i = i + 1 > listData.length ? 0 : i + 1;
    }, 3000);

    return () => clearInterval(inter);
  }, [curr, listData]);


  useEffect(() => {
    Animated.timing(bounceBigItem, {
      toValue: -30,
      duration: 2000,
      useNativeDriver: true,
    });
  }, [bounceBigItem]);

  const runAnimation = useCallback(() => {
    Animated.sequence([
      Animated.timing(bounceLittleItem, {
        toValue: -30,
        duration: 2000,
        useNativeDriver: true,
      }),
      Animated.parallel([
        Animated.timing(bounceLittleItem, {
          toValue: 20,
          duration: 1000,
          useNativeDriver: true,
        }),
        Animated.timing(scaleUp, {
          toValue: 1,
          duration: 1000,
          useNativeDriver: true,
        }),
      ]),
      Animated.delay(2000),
      Animated.timing(bounceLittleItem, {
        toValue: 100,
        duration: 1000,
        useNativeDriver: true,
      }),
    ]).start(() => {
      bounceLittleItem.setValue(-80);
      scaleUp.setValue(0.5);
      runAnimation();
    });
  }, [bounceLittleItem, scaleUp]);

  useEffect(() => runAnimation(), [runAnimation]);

  const renderViewItem = useCallback(
    (index) => {
      if (renderComponentsList?.length === 0) return;
      return renderComponentsList.map((el) => {
        return (
        <Animated.View
          key={el.id}
          style={[
            styles.orderContainer,
            {
              transform: [{translateY: bounceLittleItem}, {scale: scaleUp}],
            },
          ]}
        >
          <View style={[styles.storeImage]} />
          <Text style={styles.orderStatusText}>{el.storeName}</Text>
        </Animated.View>
      );
      })
    },
    [bounceLittleItem, listData, scaleUp, styles.orderContainer, styles.orderStatusText, styles.storeImage],
  );

  return <View style={styles.mainContainer}>{renderViewItem(curr)}</View>;
};

0 Answers
Related