React Native Flip Card 无法在翻盖上工作

React Native Flip Card not Working on flip

我正在尝试制作翻转纸牌游戏。我将 GestureFlipView 用于翻转卡片动画。我想在 3X3 网格中显示这些翻盖卡片,为此我使用了 React Native。但是问题出现了,卡片没有被翻转,而且它也表现出模糊的行为。只有最后一张卡工作正常,其他卡的行为不可预测。

Github 回购:https://github.com/akhilomar/React-Native-Number-Game

卡片屏幕:https://i.stack.imgur.com/Cliww.png

卡片组件

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

您需要正确使用ref。你可以阅读它 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} />
  


}

您遇到麻烦的主要原因是您在功能组件中使用了 this 引用。正如所解释的 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.

还需要考虑的是 FlatList 在这里是否合适。通常,此组件用于 improve performance 呈现大型列表。与其使用 FlatList,我建议使用更简单的东西,例如一组 View 组件来抽牌。这是一个基于您的代码的完整示例:

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;