Reputation: 49
I am trying to make a flip card game. I used GestureFlipView for flip card animation. I want to display these flip card in 3X3 grid and for that I have used from react native. But the problem occurs that cards are not getting flipped and it is showing vague behaviour as well. Just the last card working fine and other cards are doing unpredictable behaviour.
Github Repo: https://github.com/akhilomar/React-Native-Number-Game
CardScreen: https://i.sstatic.net/Cliww.png
Card Component
import {View, Text, SafeAreaView, TouchableOpacity} from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Cards = (props) => {
const [flipType, setFlip] = useState('left');
useEffect(() => {
})
const renderFront = () => {
return(
<TouchableOpacity onPress = {() => {
this.flipView.flipRight()
setFlip('right');
console.log("Pressed" + `${props.val}`)
}} >
<View style = {{backgroundColor:'red', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 20}}>Swipe Me</Text>
</View>
</TouchableOpacity>
);
};
const renderBack = () => {
return(
<View style = {{backgroundColor:'blue', width: 100, height: 100, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: "white", fontSize: 30}}>{props.val}</Text>
{/* <TouchableOpacity onPress = {() => {
(flipType === 'left') ? this.flipView.flipRight() : this.flipView.flipLeft();
setFlip((flipType === 'left') ? 'right' : 'left');
}} style = {{padding: 10, backgroundColor: 'purple', width: 100, height: 40, alignItems: 'center', justifyContent: 'center'}}>
<Text style = {{color: 'white'}}>Reverse</Text>
</TouchableOpacity> */}
</View>
);
};
//ref = {(ref) => this.flipView = ref}
return(
<SafeAreaView style = {{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<GestureFlipView ref = {(ref) => this.flipView = ref} width={300} height = {500}>
{renderFront()}
{renderBack()}
</GestureFlipView>
</SafeAreaView>
);
}
export default Cards;```
**Card List Component**
```import React from 'react';
import {SafeAreaView, View, FlatList, Dimensions, StyleSheet } from 'react-native';
import Cards from './Cards';
const CardScreen = () => {
// const data = ['1','2','3','4','5','6','7','8','9'];
const DATA = [
{
id: '1',
title: '1',
},
{
id: '2',
title: '2',
},
{
id: '3',
title: '3',
},
{
id: '4',
title: '4',
},
{
id: '5',
title: '5',
},
{
id: '6',
title: '6',
},
{
id: '7',
title: '7',
},
{
id: '8',
title: '8',
},
{
id: '9',
title: '9',
}
];
const Shuffle = (arr1) => {
var ctr = arr1.length, temp, index;
while (ctr > 0) {
index = Math.floor(Math.random() * ctr);
ctr--;
temp = arr1[ctr];
arr1[ctr] = arr1[index];
arr1[index] = temp;
}
return arr1;
}
const numColumns = 3;
const size = Dimensions.get('window').width/numColumns;
const styles = StyleSheet.create({
itemContainer: {
width: size,
height: size,
},
item: {
flex: 1,
margin: 3,
backgroundColor: 'lightblue',
}
});
return(
<>
<FlatList
data={DATA}
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Cards val = {item.value}/>
</View>
)}
keyExtractor={item => item.id}
numColumns={numColumns} />
{/* {
data.map((index, item) => {
return(
<View style={styles.itemContainer}>
<Cards val = {item}/>
</View>
);
})
} */}
</>
);
}
export default CardScreen;```
Upvotes: 1
Views: 1044
Reputation: 1564
The primary cause of your troubles is the fact that you are using a this
reference within a functional component. As explained here, the value of this
will be determined by how the function is called, and might even be undefined
. A more reliable approach of using this
is from a class context. For React, that means using a class component, rather than a functional component, which is what is being used here. You can read about function and class components here.
Something else to consider is if a FlatList
is appropriate here. Typically, this component is used to improve performance for rendering large lists. Instead of using a FlatList
, I would recommend using something simpler, such as a set of View
components to draw the cards. Here is a complete example based on your code:
import React, { useState } from 'react';
import { View, Dimensions, StyleSheet, Text, TouchableOpacity } from 'react-native';
import GestureFlipView from 'react-native-gesture-flip-card';
const Card = (props: any) => {
const [flipType, setFlip] = useState('left');
let flipView: any;
const onFrontPress = () => {
flipView.flipRight()
setFlip('right');
}
const cardDimensions = { width: 0.9 * props.size, height: 0.9 * props.size };
const renderFront = () => {
return (
<TouchableOpacity onPress={onFrontPress} style={[styles.front, cardDimensions]}>
<Text style={styles.frontText}>Swipe Me</Text>
</TouchableOpacity>
);
};
const renderBack = () => {
return (
<View style={[styles.back, cardDimensions]}>
<Text style={styles.backText}>{props.val}</Text>
</View>
);
};
return (
<GestureFlipView ref={(ref) => flipView = ref} width={props.size} height={props.size}>
{renderFront()}
{renderBack()}
</GestureFlipView>
);
}
const CardRow = () => {
const size = Dimensions.get('window').width / 3;
return (
<View style={styles.rowContainer}>
<Card size={size} />
<Card size={size} /{ width: 0.9 * props.size, height: 0.9 * props.size }>
<Card size={size} />
</View>
);
}
const CardScreen = () => {
return (
<View style={styles.container}>
<CardRow />
<CardRow />
<CardRow />
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
},
rowContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
},
back: {
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center'
},
backText: {
color: "white",
fontSize: 30
},
front: {
backgroundColor: 'green',
alignItems: 'center',
justifyContent: 'center',
},
frontText: {
color: "white",
fontSize: 20
}
});
export default CardScreen;
Upvotes: 1
Reputation: 3966
You need to use ref
correctly. you can Read about it here
const Cards = (props) => {
//first define ref
const flipViewRef = React.useRef();
//in onPress use it like this
<TouchableOpacity onPress = {() => {
flipViewRef.current.flipRight()
...
}} >
//in GestureFlipView assign it like this
<GestureFlipView ref={flipViewRef} />
}
Upvotes: 1