I'm using a swipe animation, the same one that is being used in apps like tinder.
The animation used to work in a Class component and in JSX but I had to change it to a function with hooks in TSX for a project. Now the animation Doensn't work anymore but it also doesn't give a error. I guess I'm missing some code that is necessary to let it work or it also can be something with the Panresponder. But I absolutely got no clue.
Thanks in advance.
const SCREEN_HEIGHT = Dimensions.get('window').height
const SCREEN_WIDTH = Dimensions.get('window').width
const { width, height } = Dimensions.get('screen')
const thumbMeasure = (width - 48 - 32) / 3
const MyComponent = (props: { index: any }) => {
const [imagesData, setImagesData] = useState<Images[]>([])
console.clear()
console.log('Images data:', imagesData)
useEffect(() => {
LogBox.ignoreLogs(['Animated: `useNativeDriver`']);
}, [])
useEffect(() => {
axios
.get<Images[]>('https://api.thecatapi.com/v1/images/search?breed_ids=beng&include_breeds=true')
.then((response: AxiosResponse) => {
setImagesData(response.data)
})
}, [])
const position = new Animated.ValueXY()
const [index, setIndex] = useState(props.index || 0)
const [panResponder, setPanResponder] = useState<any>()
const rotate = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: ['-30deg', '0deg', '10deg'],
extrapolate: 'clamp',
})
const rotateAndTranslate = {
transform: [{
rotate: rotate
},
...position.getTranslateTransform()
]
}
const likeOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [0, 0, 1],
extrapolate: 'clamp',
})
const dislikeOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 0],
extrapolate: 'clamp',
})
const nextCardOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 1],
extrapolate: 'clamp',
})
const nextCardScale = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0.8, 1],
extrapolate: 'clamp',
})
useEffect(() => {
setPanResponder( PanResponder.create({
onStartShouldSetPanResponder: (_evt, _gestureState) => true,
onPanResponderMove: (_evt, gestureState) => {
position.setValue({ x: gestureState.dx, y: gestureState.dy })
},
onPanResponderRelease: (_evt, gestureState) => {
if (gestureState.dx > 120) {
Animated.spring(position, {
toValue: { x: SCREEN_WIDTH + 100, y: gestureState.dy },
useNativeDriver: true,
}).start(() => {
setIndex( () => {
position.setValue({ x: 0, y: 0 })
return index + 1
})
})
} else if (gestureState.dx < -120) {
Animated.spring(position, {
toValue: { x: -SCREEN_WIDTH - 100, y: gestureState.dy },
useNativeDriver: true,
}).start(() => {
setIndex( () => {
position.setValue({ x: 0, y: 0 })
return index + 1
})
})
} else {
Animated.spring(position, {
toValue: { x: 0, y: 0 },
friction: 4, useNativeDriver: true,
}).start()
}
},
}))
}, [])
const Users = () => {
return imagesData.map((item, i) => {
if (i < index) {
return null
} else if (i == index) {
return (
<Animated.View
{...panResponder.panhandlers}
key={item.id}
style={[
rotateAndTranslate,
{
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: likeOpacity,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: dislikeOpacity,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
<View style={{backgroundColor: '', color: 'black', fontSize: 20, fontWeight: '800', position: 'absolute', bottom: 95, right: 40, zIndex: 1000, width: '85%', height: '20%', borderRadiusTop: 20, }}>
<Text style={{ color: 'white', fontSize: 32, fontWeight: '800' }}>
{item.breeds[0].name}
</Text>
<Text style={{ color: 'white', fontSize: 18, fontWeight: '600' }}>
{item.breeds[0].origin}
</Text>
<View style={styles.iconen}>
<Ionicons style={styles.icon} name="timer" />
<Text style={styles.subtitle}>{item.breeds[0].life_span}</Text>
<Ionicons style={styles.icon} name="barbell-outline" />
<Text style={styles.subtitle}>{item.breeds[0].weight.metric}</Text>
<Ionicons style={styles.icon} name="earth" />
<Text style={styles.subtitle}>{item.breeds[0].country_code}</Text>
</View>
</View>
</Animated.View>
)
} else {
return (
<Animated.View
key={item.id}
style={[
{
opacity: nextCardOpacity,
transform: [{ scale: nextCardScale }],
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
</Animated.View>
)
}
})
.reverse()
}
return (
<View>
<View>
{Users()}
</View>
<View style={{ height: SCREEN_HEIGHT - 80 }}>
<ButtonVote />
</View>
</View>
)
}
Related
There are 2 gradients, when I press the inactive one, I want the
active one to slowly shift the color of the other, how can I do that?
import React, { useState } from "react";
import { StyleSheet, Text, View, TouchableOpacity,Button } from "react-native";
import LinearGradient from 'react-native-linear-gradient';
import Animated, {useSharedValue,useAnimatedStyle,} from 'react-native-reanimated';
const atciveTab = ['#0067FF', '#00C2FF']
const inactiveTab = ['rgba(0,0,0,0)', 'rgba(0,0,0,0)']
const App = () => {
const [selectedTab, setSelectedTab] = useState({
tickets: true,
collectibles: false
})
const selectTicketTab = () => {
setSelectedTab({
tickets: true,
collectibles: false
})
}
const selectCollectiblesTab = () => {
setSelectedTab({
tickets: false,
collectibles: true
})
}
const offset = useSharedValue(0);
const animatedStyles = useAnimatedStyle(() => {
return {
transform: [{ translateX: offset.value * 255 }],
};
});
The gradient in the background will scroll when I click on it.
return (
<View style={styles.container}>
<TouchableOpacity
onPress={selectTicketTab}
style={styles.mainview}>
<LinearGradient
style={styles.ticketTab}
colors={selectedTab.tickets ? atciveTab : inactiveTab}
start={{ x: 1, y: 2 }}
end={{ x: 0, y: 0 }}
>
<Text style={styles.text}>Tickets</Text>
</LinearGradient>
</TouchableOpacity>
<TouchableOpacity
onPress={selectCollectiblesTab}
style={styles.mainview2}>
<LinearGradient
style={styles.collectiblesTab}
colors={selectedTab.collectibles ? atciveTab : inactiveTab}
start={{ x: 1, y: 2 }}
end={{ x: 0, y: 0 }}
>
<Text style={styles.text}>Collectibles</Text>
</LinearGradient>
</TouchableOpacity>
<Animated.View style={[styles.box, animatedStyles]} />
<Button onPress={() => (offset.value = Math.random())} title="Move" />
</View>
)
}
export default App;
I want the background color to be transferred to the other by sliding
slowly I tried many ways but I couldn't
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 20,
backgroundColor: '#050035',
flex: 1,
justifyContent: 'center'
},
text: {
fontWeight: '400',
color: 'white',
textAlign: 'center',
padding: 10,
fontSize: 14,
letterSpacing: 0.1,
},
mainview: {
width: 163,
gap: 10,
backgroundColor: 'rgba(209, 214, 219, 0.1)',
height: 40,
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
},
mainview2: {
width: 163,
gap: 10,
backgroundColor: 'rgba(209, 214, 219, 0.1)',
marginLeft: 3,
height: 40,
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
},
ticketTab: {
borderTopLeftRadius: 8,
borderBottomLeftRadius: 8,
},
collectiblesTab: {
borderTopRightRadius: 8,
borderBottomRightRadius: 8,
},
box: {
width: 150,
height: 150,
backgroundColor: 'red'
}
})
I want to implement a swipe to delete feature on flatlist data. I can get the swipe to work, but it only registers after the touch input is lifted. When I start dragging, the card does not initially drag, but it swipes after I lift the input. How can I make it so it starts dragging when I start moving the card?
Current Code:
export default class AppleStyleSwipeableRow extends Component {
private renderRightAction = (x: number, dragX) => {
const trans = dragX.interpolate({
inputRange: [0, 1],
outputRange: [x, 0],
extrapolate: "clamp",
});
const pressHandler = () => {
this.close();
Alert.alert("hi");
};
return (
<Animated.View
style={{
flex: 1,
borderRadius: 15,
height: 120,
transform: [{ translateX: trans }],
}}
>
<RectButton
style={[
styles.rightAction,
{ backgroundColor: "transparent", height: 50 },
]}
onPress={pressHandler}
>
<SquircleView
style={StyleSheet.absoluteFill}
squircleParams={{
cornerSmoothing: 0.6,
cornerRadius: 15,
fillColor: "#FF3B30",
}}
>
<Image
style={{
width: 17.37 * 1.5,
height: 19.66 * 1.5,
justifyContent: "center",
alignSelf: "center",
top: 40,
right: 3.5,
}}
source={require("../../assets/trash.fill.png")}
></Image>
</SquircleView>
</RectButton>
</Animated.View>
);
};
private renderRightActions = (
progress: Animated.AnimatedInterpolation,
_dragAnimatedValue: Animated.AnimatedInterpolation
) => (
<View
style={{
width: 90,
flexDirection: I18nManager.isRTL ? "row-reverse" : "row",
}}
>
{this.renderRightAction(90, progress)}
</View>
);
private swipeableRow?: Swipeable;
private updateRef = (ref: Swipeable) => {
this.swipeableRow = ref;
};
private close = () => {
this.swipeableRow?.close();
};
render() {
const { children } = this.props;
return (
<Swipeable
containerStyle={{ borderRadius: 15 }}
childrenContainerStyle={{ backgroundColor: "white", borderRadius: 15 }}
ref={this.updateRef}
friction={3}
enableTrackpadTwoFingerGesture
rightThreshold={40}
renderRightActions={this.renderRightActions}
>
{children}
</Swipeable>
);
}
}
const styles = StyleSheet.create({
actionText: {
color: "white",
fontSize: 16,
backgroundColor: "transparent",
padding: 10,
},
rightAction: {
alignItems: "center",
flex: 1,
justifyContent: "center",
left: 10,
},
});
ScreenA.tsx
const RenderItem = ({ item }) => {
return (
<View style={{ height: 120, width: W_WIDTH * 0.9, zIndex: -100 }}>
<Image
source={require("../../assets/pin.png")}
style={{
position: "absolute",
width: 40,
height: 40,
}}
/>
<Text
style={{
fontSize: 22,
paddingRight: 16,
color: "black",
fontFamily: "Medium",
left: 45,
top: 6,
}}
>
Foo
</Text>
</View>
);
};
const ScreenA = () => {
const SwipeableRow = ({ item }) => {
return (
<RectButton
style={{
width: W_WIDTH * 0.9,
height: 120,
alignItems: "center",
backgroundColor: "#f3f2f8",
borderRadius: 10,
marginHorizontal: 20,
marginTop: 20,
}}
onPress={() =>
navigation.navigate("ScreenB")
}
>
<AppleStyleSwipeableRow>
<RenderItem item={item} />
</AppleStyleSwipeableRow>
</RectButton>
);
};
return (
<StatusBar style={colorScheme == "dark" ? "light" : "dark"} />
<ScrollView
style={[
styles.container,
{
backgroundColor: colorScheme == "dark" ? "black" : "white",
},
]}
contentInsetAdjustmentBehavior="automatic"
keyboardDismissMode="on-drag"
>
<FlatList
data={bookmarks}
keyExtractor={(item) => item.country}
renderItem={({ item }) => <SwipeableRow item={item} />}
// renderItem={renderItem}
showsVerticalScrollIndicator={false}
/>
</ScrollView>
);
};
}
Does your RectButton have an onPressIn prop? That's what you'll need to use - if it doesn't have it, switch it out for a Pressable or other component with this prop.
I am trying to rotate the view but it's working well if I didn't set the borderRadius. But It's not working well if I set the borderRadius.
Here is a code
inner: {
width: '100%',
height: '100%',
borderRadius: 1,
borderWidth: 5,
borderStyle: 'solid',
borderColor: 'rgba(0, 255, 170, 0.3)',
borderRightWidth: 0,
borderTopWidth: 0,
}
const value = useRef(new Animated.Value(0)).current;
const rotate = () => {
value.setValue(0);
Animated.timing(value, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start(() => {
rotate();
});
};
useEffect(() => {
rotate();
}, [rotate]);
<Animated.View
style={[
{width: '100%', height: '100%', backgroundColor: 'transparent'},
{
transform: [
{
rotate: '15deg',
},
],
},
]}>
<View style={[styles.inner]} />
</Animated.View>
[
I'm stuck with converting a Class component to a function / const while using hooks.
I'm getting this Warning: Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
I googled this warning but only saw this warning with Classes, did I convert this Class wrong?
const MyComponent = (props) => {
const position = new Animated.ValueXY()
const [index, setIndex] = useState(props.index || 0)
const rotate = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: ['-30deg', '0deg', '10deg'],
extrapolate: 'clamp',
})
const rotateAndTranslate = {
transform: [
{
rotate: rotate,
},
position.getTranslateTransform(),
],
}
const likeOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [0, 0, 1],
extrapolate: 'clamp',
})
const dislikeOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 0],
extrapolate: 'clamp',
})
const nextCardOpacity = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 1],
extrapolate: 'clamp',
})
const nextCardScale = position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0.8, 1],
extrapolate: 'clamp',
})
useEffect(() => {
PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderMove: (evt, gestureState) => {
position.setValue({ x: gestureState.dx, y: gestureState.dy })
},
onPanResponderRelease: (evt, gestureState) => {
if (gestureState.dx > 120) {
Animated.spring(position, {
toValue: { x: SCREEN_WIDTH + 100, y: gestureState.dy },
useNativedriver: true,
}).start(() => {
setIndex(index + 1, () => {
position.setValue({ x: 0, y: 0 })
})
})
} else if (gestureState.dx < -120) {
Animated.spring(position, {
toValue: { x: -SCREEN_WIDTH - 100, y: gestureState.dy },
useNativedriver: true,
}).start(() => {
setIndex(index + 1, () => {
position.setValue({ x: 0, y: 0 })
})
})
} else {
Animated.spring(position, {
toValue: { x: 0, y: 0 },
friction: 4,
useNativedriver: true,
}).start()
}
},
})
}, [])
const Users = () => {
return imagesData
.map((item, i) => {
if (i < index) {
return null
} else if (i == index) {
return (
<Animated.View
{...PanResponder.panHandlers}
key={item.id}
style={[
rotateAndTranslate,
{
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: likeOpacity,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: dislikeOpacity,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
<View
style={{
backgroundColor: '',
color: 'black',
fontSize: 20,
fontWeight: '800',
position: 'absolute',
bottom: 95,
right: 40,
zIndex: 1000,
width: '85%',
height: '20%',
borderRadiusTop: 20,
}}
>
<Text
style={{ color: 'white', fontSize: 32, fontWeight: '800' }}
>
Black cat
</Text>
<Text
style={{ color: 'white', fontSize: 18, fontWeight: '600' }}
>
Black cat family
</Text>
<View style={styles.iconen}>
<Ionicons style={styles.icon} name="timer" />
<Text style={styles.subtitle}>12 -14</Text>
<Ionicons style={styles.icon} name="barbell-outline" />
<Text style={styles.subtitle}>12 - 14</Text>
<Ionicons style={styles.icon} name="earth" />
<Text style={styles.subtitle}>Belgium</Text>
</View>
</View>
</Animated.View>
)
} else {
return (
<Animated.View
key={item.id}
style={[
{
opacity: nextCardOpacity,
transform: [{ scale: nextCardScale }],
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
</Animated.View>
)
}
})
.reverse()
}
return (
<View>
<View>{Users}</View>
<View style={{ height: SCREEN_HEIGHT - 80 }}>
<ButtonVote />
</View>
</View>
)
}
Users is a component, you should call it like
<Users />
instead of
{Users}
I'm using Axios to retrieve my data from my API in this Class component in TSX.
It doesn't give any error, it just doesn't show my Images or not even the data in a console.log. I'm now using a class component with tsx because in my previous attempts to let a animated slider work I used: Class component in jsx, Class component in tsx, Function in JSX with hooks aswell in TSX. At every attempt there were different errors that I couldn't solve that's why I'm using this strategy now and I guess I'm close now to the sollution, it's just the Data that's not viewing.
Thanks in advance
class MyComponent extends Component {
componentDidMount() {
LogBox.ignoreLogs(['Animated: `useNativeDriver`'])
}
position
rotate: number
rotateAndTranslate
likeOpacity
dislikeOpacity
nextCardOpacity
nextCardScale
PanResponder
imagesData: Images[]
mySpecialFunction() {
console.log('Images data:', this.imagesData)
}
constructor(props) {
super(props)
LogBox.ignoreLogs(['Animated: `useNativeDriver`'])
axios
.get<Images[]>(
'https://api.thecatapi.com/v1/images/search?breed_ids=beng&include_breeds=true',
)
.then((response: AxiosResponse) => {
this.imagesData = response.data
})
this.position = new Animated.ValueXY()
this.state = {
currentIndex: 0,
}
this.rotate = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: ['-30deg', '0deg', '10deg'],
extrapolate: 'clamp',
})
this.rotateAndTranslate = {
transform: [
{
rotate: this.rotate,
},
...this.position.getTranslateTransform(),
],
}
this.likeOpacity = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [0, 0, 1],
extrapolate: 'clamp',
})
this.dislikeOpacity = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 0],
extrapolate: 'clamp',
})
this.nextCardOpacity = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0, 1],
extrapolate: 'clamp',
})
this.nextCardScale = this.position.x.interpolate({
inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
outputRange: [1, 0.8, 1],
extrapolate: 'clamp',
})
}
UNSAFE_componentWillMount() {
this.PanResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderMove: (evt, gestureState) => {
this.position.setValue({ x: gestureState.dx, y: gestureState.dy })
},
onPanResponderRelease: (evt, gestureState) => {
if (gestureState.dx > 120) {
Animated.spring(this.position, {
toValue: { x: SCREEN_WIDTH + 100, y: gestureState.dy },
useNativedriver: true,
}).start(() => {
this.setState({ currentIndex: this.state.currentIndex + 1 }, () => {
this.position.setValue({ x: 0, y: 0 })
})
})
} else if (gestureState.dx < -120) {
Animated.spring(this.position, {
toValue: { x: -SCREEN_WIDTH - 100, y: gestureState.dy },
useNativedriver: true,
}).start(() => {
this.setState({ currentIndex: this.state.currentIndex + 1 }, () => {
this.position.setValue({ x: 0, y: 0 })
})
})
} else {
Animated.spring(this.position, {
toValue: { x: 0, y: 0 },
friction: 4,
useNativedriver: true,
}).start()
}
},
})
}
renderUsers = () => {
if (this.imagesData) {
return this.imagesData
.map((item, i) => {
if (i < this.state.currentIndex) {
return null
} else if (i == this.state.currentIndex) {
return (
<Animated.View
{...this.PanResponder.panHandlers}
key={item.id}
style={[
this.rotateAndTranslate,
{
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: this.likeOpacity,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: this.dislikeOpacity,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
<View
style={{
backgroundColor: '',
color: 'black',
fontSize: 20,
fontWeight: '800',
position: 'absolute',
bottom: 95,
right: 40,
zIndex: 1000,
width: '85%',
height: '20%',
borderRadiusTop: 20,
}}
>
<Text
style={{ color: 'white', fontSize: 32, fontWeight: '800' }}
>
Black cat
</Text>
<Text
style={{ color: 'white', fontSize: 18, fontWeight: '600' }}
>
Black cat family
</Text>
<View style={styles.iconen}>
<Ionicons style={styles.icon} name="timer" />
<Text style={styles.subtitle}>
{item.breeds[0].life_span}
</Text>
<Ionicons style={styles.icon} name="barbell-outline" />
<Text style={styles.subtitle}>
{item.breeds[0].weight.metric}
</Text>
<Ionicons style={styles.icon} name="earth" />
<Text style={styles.subtitle}>
{item.breeds[0].country_code}
</Text>
</View>
</View>
</Animated.View>
)
} else {
return (
<Animated.View
key={item.id}
style={[
{
opacity: this.nextCardOpacity,
transform: [{ scale: this.nextCardScale }],
height: SCREEN_HEIGHT - 120,
width: SCREEN_WIDTH,
padding: 10,
position: 'absolute',
},
]}
>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '-30deg' }],
position: 'absolute',
top: 50,
left: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'green',
color: 'green',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
LIKE
</Text>
</Animated.View>
<Animated.View
style={{
opacity: 0,
transform: [{ rotate: '30deg' }],
position: 'absolute',
top: 50,
right: 40,
zIndex: 1000,
}}
>
<Text
style={{
borderWidth: 1,
borderColor: 'red',
color: 'red',
fontSize: 32,
fontWeight: '800',
padding: 10,
}}
>
NOPE
</Text>
</Animated.View>
<Image
style={{ height: '86%', width: null, borderRadius: 10 }}
source={{ uri: `${item.url}` }}
/>
</Animated.View>
)
}
})
.reverse()
}
}
render() {
return (
<View>
<View>{this.renderUsers()}</View>
<View style={{ height: SCREEN_HEIGHT - 80 }}>
<ButtonVote />
</View>
</View>
)
}
}
Try this way by using state for reflecting changes after API respond
class MyComponent extends Component {
state = {
imagesData: [],
};
// rest of the code remains the same
componentDidMount() {
axios.get(`xxxxxx`).then((res) => {
const imagesData = res.data;
this.setState({ imagesData });
});
}
renderUsers = () => {
if (this.state.imagesData) {
return this.state.imagesData.map((item, i) => {}).reverse();
}
};
render() {
return <View></View>;
}
}