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>;
};