0

When I open the application on the web using the npx expo start --tunnel command, I can swipe and flip the cards, but it doesn't work in expo go. I can see the cards, but they don't move. It's like the touchscreen doesn't work at all.How can i fix?

package.json

{
  "name": "word-cards",
  "version": "1.0.0",
  "main": "expo-router/entry",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@expo/metro-runtime": "~3.2.3",
    "@react-native-async-storage/async-storage": "1.23.1",
    "axios": "^1.7.7",
    "expo": "^51.0.0",
    "expo-constants": "~16.0.1",
    "expo-font": "^12.0.10",
    "expo-linking": "~6.3.1",
    "expo-router": "~3.5.9",
    "expo-splash-screen": "~0.27.4",
    "expo-status-bar": "~1.12.1",
    "npm-upgrade": "^3.1.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.74.5",
    "react-native-deck-swiper": "^2.0.17",
    "react-native-dotenv": "^3.4.11",
    "react-native-flip-card": "^3.5.7",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-reanimated": "~3.10.1",
    "react-native-safe-area-context": "4.10.5",
    "react-native-screens": "3.31.1",
    "react-native-swipe-gestures": "^1.0.5",
    "react-native-web": "~0.19.10"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}

index.js

import React, { useState, useRef, useCallback, useEffect } from 'react';
import { View, Text, StyleSheet, Dimensions, TouchableWithoutFeedback, Animated } from 'react-native';
import Swiper from 'react-native-deck-swiper';
import AsyncStorage from '@react-native-async-storage/async-storage';

const { width, height } = Dimensions.get('window');

const flashcards = [
  { id: 1, german: 'Ja', english: 'Yes' },
  { id: 2, german: 'Nein', english: 'No' },
  { id: 3, german: 'Bitte', english: 'Please' },
 ];


const shuffleArray = (array) => {
  return array.sort(() => Math.random() - 0.5);
};

export default function App() {
  const [currentIndex, setCurrentIndex] = useState(0);
  const [cards, setCards] = useState(shuffleArray([...flashcards])); 
  const [label, setLabel] = useState('');
  const [cardFrequency, setCardFrequency] = useState({});
  const flipAnimation = useRef(new Animated.Value(0)).current;
  const swiperRef = useRef(null);

 
  useEffect(() => {
    const loadCardData = async () => {
      try {
        const storedFrequency = await AsyncStorage.getItem('cardFrequency');
        if (storedFrequency) {
          setCardFrequency(JSON.parse(storedFrequency));
        }
      } catch (error) {
        console.log("Error loading card data", error);
      }
    };
    loadCardData();
  }, []);

  const flipCard = useCallback(() => {
    Animated.spring(flipAnimation, {
      toValue: flipAnimation._value === 0 ? 180 : 0,
      friction: 8,
      tension: 10,
      useNativeDriver: true,
    }).start();
  }, [flipAnimation]);

  const frontInterpolate = flipAnimation.interpolate({
    inputRange: [0, 180],
    outputRange: ['0deg', '180deg'],
  });
  const backInterpolate = flipAnimation.interpolate({
    inputRange: [0, 180],
    outputRange: ['180deg', '360deg'],
  });

  const frontAnimatedStyle = {
    transform: [{ rotateY: frontInterpolate }],
  };
  const backAnimatedStyle = {
    transform: [{ rotateY: backInterpolate }],
  };


  const updateCardOrder = () => {
    const newCards = [...flashcards].sort((a, b) => {
      const freqA = cardFrequency[a.id] || 1; 
      const freqB = cardFrequency[b.id] || 1;
      return Math.random() * (1 / freqA) - Math.random() * (1 / freqB);
    });
    setCards(newCards);
  };

  const handleSwiping = useCallback((x) => {
    if (x > 0) {
      setLabel('TRUE');
    } else if (x < 0) {
      setLabel('FALSE');
    } else {
      setLabel('');
    }
  }, []);

  const handleSwiped = useCallback((cardIndex) => {
    const card = cards[cardIndex % cards.length];
    const newFrequency = { ...cardFrequency };

    if (label === 'TRUE') {
      newFrequency[card.id] = (newFrequency[card.id] || 1) * 0.5; 
    } else if (label === 'FALSE') {
      newFrequency[card.id] = (newFrequency[card.id] || 1) * 2; 
    }

    setCardFrequency(newFrequency);
    AsyncStorage.setItem('cardFrequency', JSON.stringify(newFrequency)); 
    setCurrentIndex((prevIndex) => (prevIndex + 1) % flashcards.length);
    setLabel('');
    flipAnimation.setValue(0);
    updateCardOrder();
  }, [cardFrequency, cards, label, flipAnimation]);

  const handleSwipedAll = useCallback(() => {
    if (swiperRef.current) {
      swiperRef.current.jumpToCardIndex(0);
    }
    setCurrentIndex(0);
    flipAnimation.setValue(0);
    setLabel('');
  }, []);

  return (
    <View style={styles.container}>
      <Swiper
        ref={swiperRef}
        cards={cards}
        renderCard={(card) => (
          <TouchableWithoutFeedback onPress={flipCard}>
            <View style={styles.cardContainer}>
              <Animated.View style={[styles.card, frontAnimatedStyle]}>
                <Text style={styles.text}>{card.german}</Text>
              </Animated.View>
              <Animated.View style={[styles.card, styles.cardBack, backAnimatedStyle]}>
                <Text style={styles.text}>{card.turkish}</Text>
              </Animated.View>
              {label !== '' && (
                <View style={label === 'TRUE' ? styles.correctLabel : styles.wrongLabel}>
                  <Text style={styles.labelText}>{label}</Text>
                </View>
              )}
            </View>
          </TouchableWithoutFeedback>
        )}
        onSwiped={handleSwiped}
        onSwiping={handleSwiping}
        cardIndex={currentIndex}
        backgroundColor={'#F5FCFF'}
        stackSize={2}
        showSecondCard={false}
        animateCardOpacity
        swipeBackCard
        containerStyle={styles.swiperContainer}
        cardVerticalMargin={80}
        onSwipedAll={handleSwipedAll}
        infinite
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
    justifyContent: 'center',
    alignItems: 'center',
  },
  swiperContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  cardContainer: {
    width: width * 0.8,
    height: height * 0.6,
  },
  card: {
    width: '100%',
    height: '100%',
    borderRadius: 8,
    borderWidth: 2,
    borderColor: '#E8E8E8',
    justifyContent: 'center',
    backgroundColor: 'white',
    backfaceVisibility: 'hidden',
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5,
  },
  cardBack: {
    position: 'absolute',
    top: 0,
  },
  text: {
    textAlign: 'center',
    fontSize: 24,
    fontWeight: 'bold',
  },
  correctLabel: {
    position: 'absolute',
    top: 20,
    left: 20,
    backgroundColor: 'green',
    padding: 10,
    borderRadius: 5,
  },
  wrongLabel: {
    position: 'absolute',
    top: 20,
    right: 20,
    backgroundColor: 'red',
    padding: 10,
    borderRadius: 5,
  },
  labelText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

Thinking that it might be a problem with my phone, I wanted to run it with Expo Snack, but I couldn't try it because I couldn't install the packages.

1 Answer 1

0

I had this issue and I solved it by toggling (m) the dev menu in the terminal. Seems the app thinks the dev menu is present/shown when its not.

Sign up to request clarification or add additional context in comments.

1 Comment

thank u so much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.