Я пытаюсь понять, почему мое приложение не работает должным образом. Основная предпосылка c состоит в том, что пользователь может выбирать различные типы карточек, которые он хочет просмотреть. Они разбиты на различные типы и выбираются с помощью флажков. Затем этот массив настроек передается на другой экран, где я беру свои данные из firebase и конвертирую их в массив. Затем эти массивы сравниваются друг с другом, и, если соблюдаются правильные критерии, они добавляются в новую колоду. Затем эта новая колода визуализируется и перемещается с помощью кнопок «Назад» и «Далее». Любая помощь будет принята с благодарностью.
Моя текущая ошибка говорит о том, что длина не определена, потому что при построении колоды мне нужно go через начальную колоду карт (массив firebase).
Current error:
×
TypeError: Cannot read property 'length' of undefined
buildDeck
C:/Users/Langley/Desktop/ArticCards/screens/CardScreen.js:39
36 | let deck = new Array();
37 |
38 | for(var i = 0; i < passDeck.length; i++){
> 39 | for(var j = 0; j < currentSettings.length; j++){
| ^ 40 | if((passDeck.cType[i] == currentSettings[j].arType) && (currentSettings[j].addCV == true)){
41 | deck.push(passDeck[i]);
42 | }
Главный экран
import React, { useState, useEffect } from "react";
import { StyleSheet, Text, Keyboard, TouchableOpacity, View, TouchableWithoutFeedback, Image } from "react-native";
import { Button } from "react-native-elements";
import { Feather } from "@expo/vector-icons";
import { initArticDB, setupArticListener } from '../helpers/fb-settings';
const HomeScreen = ({route, navigation}) => {
const [ deck, setDeck] = useState([]);
useEffect(() => {
try {
initArticDB();
} catch (err) {
console.log(err);
}
setupArticListener((items) => {
setDeck(items);
});
}, []);
useEffect(() => {
if(route.params?.articCard){
setCard({imageUrl: state.imageUrl, word: state.word, aType: state.aType, cType: state.cType, mastery: state.mastery})
}
if(route.params?.deck){
setDeck({imageUrl: state.imageUrl, word: state.word, aType: state.aType, cType: state.cType, mastery: state.mastery})
}
if(route.params?.articType){
setArticType({arType: state.arType, addCV: state.addCV})
}
}, [route.params?.articType, route.params?.deckeck, route.params?.articCard] );
navigation.setOptions({
headerRight: () => (
<TouchableOpacity
onPress={() =>
navigation.navigate('Settings')
}
>
<Feather
style={styles.headerButton}
name="settings"
size={24}
color="#fff"
/>
</TouchableOpacity>
),
headerLeft: () => (
<TouchableOpacity
onPress={() =>
navigation.navigate('About')
}
>
<Text style={styles.headerButton}> About </Text>
</TouchableOpacity>
),
});
return(
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.container}>
<Text style={styles.textmenu}>Welcome to Artic Cards</Text>
<Text style={styles.textsubmenu}>Press Start to Begin!</Text>
<Image source={require('../assets/5-snowflake-png-image.png')}
style={{width: 300, height: 300, alignSelf: 'center'}}/>
<Button
title="Start"
style={styles.buttons}
onPress={() => navigation.navigate('Cards',
{passDeck: deck})}
/>
<Button
title="Progress"
style={styles.buttons}
onPress={() => navigation.navigate('Progress')}
/>
<Button
title="Customize"
style={styles.buttons}
onPress={() => navigation.navigate('Customize')}
/>
</View>
</TouchableWithoutFeedback>
);
};
const styles = StyleSheet.create({
container: {
padding: 10,
backgroundColor: '#E8EAF6',
flex: 1,
justifyContent: 'center'
},
textmenu: {
textAlign: 'center',
fontSize: 30
},
textsubmenu:{
textAlign: 'center',
fontSize: 15
},
headerButton: {
color: '#fff',
fontWeight: 'bold',
margin: 10,
},
buttons: {
padding: 10,
},
inputError: {
color: 'red',
},
input: {
padding: 10,
},
resultsGrid: {
borderColor: '#000',
borderWidth: 1,
},
resultsRow: {
flexDirection: 'row',
borderColor: '#000',
borderBottomWidth: 1,
},
resultsLabelContainer: {
borderRightWidth: 1,
borderRightColor: '#000',
flex: 1,
},
resultsLabelText: {
fontWeight: 'bold',
fontSize: 20,
padding: 10,
},
resultsValueText: {
fontWeight: 'bold',
fontSize: 20,
flex: 1,
padding: 10,
},
});
export default HomeScreen;
Экран настроек
import React, {useState, useEffect} from 'react';
import {StyleSheet, TouchableOpacity, View} from "react-native";
import {Text, CheckBox} from "react-native-elements";
import {FlatList } from "react-native-gesture-handler";
//this is broken some how can't figure out why.
const SettingsScreen = ({route, navigation}) =>{
//create a screen with checkbox fields. One for the consonant-vowel field and the other for the alphabet.
//Both of which will be using flatlists preferably side by side
//A card will only be counted if it meets both values being marked true (category and alpha)
const [articType, setArticType] = useState([
{arType: 'CV', addCV: true},
{arType: 'VC', addCV: true},
{arType: 'VV', addCV: true},
{arType: 'VCV', addCV: true},
{arType: 'CVCV', addCV: true},
{arType: 'C1V1C1V2', addCV: true},
{arType: 'C1V1C2V2', addCV: true},
]);
navigation.setOptions({
headerRight: () => (
<TouchableOpacity onPress={() => navigation.navigate('Home')}>
<Text style={styles.headerButton}> Cancel </Text>
</TouchableOpacity>
),
headerLeft: () => (
<TouchableOpacity
onPress={() => {
// navigate back with new settings.
navigation.navigate('Home', {
currentSetting: articType
});
}}
>
<Text style={styles.headerButton}> Save </Text>
</TouchableOpacity>
),
});
const renderCVType = ({index, item}) =>{
return(
<CheckBox
title={item.arType}
checked={item.addCV}
onPress={() => {
let newArr = [... articType];
newArr[index] = {...item, addCV: !item.addCV};
setArticType(newArr);
console.log(newArr);
}}
/>
)
}
return(
<View style={styles.container}>
<Text style={styles.textmenu}>Artic Type</Text>
<Text style={styles.textsubmenu}>Select what words to include based on their cononants and vowels</Text>
<FlatList
keyExtractor={(item) => item.arType}
data={articType}
renderItem={renderCVType}
/>
</View>
)
}
const styles = StyleSheet.create({
container: {
padding: 10,
backgroundColor: '#E8EAF6',
flex: 1,
},
textmenu: {
textAlign: 'center',
fontSize: 30
},
textsubmenu:{
textAlign: 'center',
fontSize: 15
},
});
export default SettingsScreen;
Экран карты
import React, { useState, useRef, useEffect } from "react";
import { StyleSheet, Text, View } from "react-native";
import { Button, Card } from "react-native-elements";
import { updateArtic } from "../helpers/fb-settings";
import { State } from "react-native-gesture-handler";
//Cannot navigate to this page, not sure why
//general formatting and importing of the deck. Probably put shuffle function here with imported array
//Next and previous buttons should bascially refresh page and give next or previous card
//mastery probably will require setupArticListener (this needs clarification though)
//Deck will be imported here and the information from SettingScreen will be imported here as well
const CardScreen = ({route, navigation}) =>{
const { currentSettings, passDeck } = route.params;
const renderCard = ({index, item}) => {
<View>
<Card
title={item.word}
image={{uri: item.imageUrl}}>
<Text> {item.cType} </Text>
</Card>
</View>
}
const renderMastery = ({index, item}) =>{
return(
<CheckBox
title={'Mastered?'}
checked={!item.mastery}
onPress={() => {
updateArtic({ ...item, mastery: !item.mastery });
}}
/>
)
}
function buildDeck(){
let deck = new Array();
for(var i = 0; i < passDeck.length; i++){
for(var j = 0; j < currentSettings.length; j++){
if((passDeck.cType[i] == currentSettings[j].arType) && (currentSettings[j].addCV == true)){
deck.push(passDeck[i]);
}
}
}
return deck;
}
function nextCard(){
var k = deck.indexOf();
if( (k+1) <= deck.length){
return deck[k+1];
} else{
return deck[0];
}
}
function previousCard(){
var k = deck.indexOf();
if( (k-1) >= 0){
return deck[k-1];
} else{
return deck[(deck.length - 1)];
}
}
buildDeck();
return(
<View>
<Text>Cards</Text>
{renderCard(deck)}
<View style={styles.row}>
<Button
title='Next'
onPress={
nextCard()
}
/>
renderItem{renderMastery}
<Button
title='Previous'
onPress = {
previousCard()
}
/>
</View>
</View>
)
}
const styles= StyleSheet.create({
row: {
flexDirection: 'row',
flex: 1,
marginBottom: 1
},
})
export default CardScreen;