Cannot read data from firestore database to react native project - javascript

I am relatively new to react natuve and I am reading data from my firestore db and I can see the title and id in my console after:
console.log(doc.id, doc.data());
but the items dont show in my flatlist and it just displays a constant loading symbol
this is my code and i cannot figure out why it wont load into my flatlist. Any help is appreciated
`
import { Pressable, Text, TextInput, View, StyleSheet,
SafeAreaView, FlatList, ActivityIndicator } from 'react-native'
import React, { useState, useEffect } from 'react'
import Exercise from '../../components/Exercise'
import { MaterialIcons } from '#expo/vector-icons';
import { auth, app, db, getFirestore, collection, addDoc, getDocs } from '../../firebase'
const WorkoutScreen = () => {
const [exerciseTitle, setTitle] = useState('');
const [exerciseList, setExerciseList] = useState([]);
const addExercise = async() => {
try {
const docRef = await addDoc(collection(db, "Exercise"), {
title: exerciseTitle,
isChecked: false,
});
console.log("Document written with ID: ", docRef.id);
setTitle("");
} catch (e) {
console.error("Error adding document: ", e);
}
};
const getExercise = async() => {
const querySnapshot = await getDocs(collection(db, "Exercise"));
querySnapshot.forEach((doc) => {
console.log(doc.id, doc.data());
setExerciseList({
...doc.data(),
id: doc.id,
title: doc.exerciseTitle,
});
});
};
useEffect ( () => {
getExercise();
}, []);
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
{/* heading */}
<Text style={styles.heading}>Workout List</Text>
{/* shopping items */}
<Text style={styles.noOfExercises}>0</Text>
{/* delete all */}
<Pressable>
<MaterialIcons name="delete" size={32} color="black" />
</Pressable>
</View>
{exerciseList.length > 0 ? (
<FlatList
data={exerciseList}
renderItem ={({item}) => <ExerciseItem title={item.exerciseTitle}/>}
keyExtractor={(item) => item.id}
/>
) : (
<ActivityIndicator />
)}
<TextInput
placeholder='Enter Excercise'
style={styles.input}
value={exerciseTitle}
onChangeText={(text) => setTitle(text)}
onSubmitEditing={addExercise}
/>
</SafeAreaView>
)
}
export default WorkoutScreen
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
flexDirection: 'row',
width: '90%',
alignSelf: 'center',
padding: 10,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 10,
},
heading: {
fontWeight: '900',
fontStyle: 'bold',
fontSize: 30,
flex: 1,
marginTop: 20,
},
noOfExercises: {
fontSize: 20,
fontWeight: '500',
marginRight: 20,
},
input: {
backgroundColor: 'lightgrey',
padding: 10,
fontSize: 17,
width: '90%',
alignSelf: 'center',
marginTop: 'auto',
borderRadius: 10,
}
})
`

The problem is here:
setExerciseList({
...doc.data(),
id: doc.id,
title: doc.exerciseTitle,
});
You're setting exerciseList to be an object, yet your rendering code expects it to be an array:
{exerciseList.length > 0 ? ...
Since you don't define a length property in the object, it ends up always render the <ActivityIndicator />.
What you'll want to do is set the entire array of documents in the state, for example with:
const getExercise = async() => {
const querySnapshot = await getDocs(collection(db, "Exercise"));
setExerciseList(querySnapshot.docs.map((doc) => {
return { ...doc.data(), id: doc.id };
});
};

Related

Firebase v9 not adding docs

I'm working with Firebase v9. The authentication works fine, but the Firestore does not work me for some reason. I don't even get an error--it just doesn't do anything.
I tried addDocs() but still nothing works.
EDIT: actually , i was using the firebase #9.1.0 i upgraded it to #9.6.7 and it worked perfectly fine ! i had to downgrade from #9.6.8 ( the latest ) to #9.1.0 because of the error ( Can't find variable: IDBIndex ) !
import React, { useLayoutEffect, useState } from "react";
import {
Text,
View,
StyleSheet,
TextInput,
TouchableOpacity,
KeyboardAvoidingView,
Platform,
ScrollView,
Alert,
} from "react-native";
import { AntDesign, Ionicons } from "#expo/vector-icons";
import { doc, setDoc } from "firebase/firestore";
import { db } from "../../firebase/firebaseConfig";
const NewChat = ({ navigation }) => {
const [input, setInput] = useState("");
useLayoutEffect(() => {
navigation.setOptions({
title: "Add a new Chat",
headerBackTitle: "Chats",
});
}, [navigation]);
const AddChat = async () => {
const myDoc = doc(db, "Chats", input);
const docData = {
chatName: input,
};
setDoc(myDoc, docData).then(() => {
navigation.goBack();
});
};
return (
<ScrollView>
<View
style={{
marginTop: 20,
marginHorizontal: 20,
borderColor: "black",
borderWidth: 1,
}}
>
<View style={styles.container}>
<AntDesign
name="wechat"
size={40}
color="black"
style={{ alignSelf: "center" }}
/>
<TextInput
placeholder="Enter a chat name"
value={input}
onChangeText={(text) => {
setInput(text);
}}
style={{ flexGrow: 1, marginLeft: 20 }}
/>
<TouchableOpacity style={{ alignSelf: "center" }} onPress={AddChat}>
<Ionicons name="checkmark-done-circle" size={40} color="black" />
</TouchableOpacity>
</View>
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flexDirection: "row",
backgroundColor: "white",
justifyContent: "center",
height: 60,
},
});
export default NewChat;
The function setDoc() asynchronously returns a promise which means all you're missing is the await keyword before you call the function.
const AddChat = async () => {
const myDoc = doc(db, "Chats", input);
const docData = {
chatName: input,
};
await setDoc(myDoc, docData).then(() => {
navigation.goBack();
});
};
Edit: I think I see the real problem, It has to do with the v9 document reference. Try using collection() within the document reference.
const AddChat = async () => {
const myDoc = doc(collection(db, "Chats"), input);
const docData = {
chatName: input,
};
await setDoc(myDoc, docData).then(() => {
navigation.goBack();
});
};

delete list element using filter method

I am working on todo list in native , i have a function called onDelete but when i click on it , it delete all element in list and after then program crashed.
this is my main file where i have stored value as key , value pair
export default function App() {
const [courseGoal, setCourseGoal] = useState([]);
const [count, setCount] = useState('');
const submitHandler = () => {
setCourseGoal((currGoal) => [
...currGoal,
{ key: Math.random().toString(), value: count },
]);
};
console.log('App', courseGoal)
return (
<View style={styles.container}>
<SearchBar
setCourseGoal={setCourseGoal}
count={count}
setCount={setCount}
submitHandler={submitHandler}
/>
<ListItem courseGoal={courseGoal} setCourseGoal={setCourseGoal} courseGoal={courseGoal}/>
</View>
);
}
this is my list component where i am facing issue, you can see ondelete here.
import React from "react";
import { StyleSheet, Text, TouchableOpacity } from "react-native";
import { FlatList } from "react-native-web";
export default function ListItem(props) {
const onDelete = (goalId) => {
props.setCourseGoal((currGoal) => {
currGoal.filter((goal) => goal.key !== goalId);
console.log("clicked", props.courseGoal[0].key);
});
};
return (
<FlatList
data={props.courseGoal}
keyExtractor={(item, index) => item.key}
renderItem={(itemData) => (
<TouchableOpacity
onPress={onDelete.bind(itemData.item.key)}
activeOpacity={0.2}
>
<Text style={styles.listData}>{itemData.item.value}</Text>
{console.log(itemData.item.key)}
</TouchableOpacity>
)}
/>
);
}
this is my main component where i have my search input
import React from "react";
import { View, Text, StyleSheet, Pressable, TextInput } from "react-native";
export default function SearchBar(props) {
const onInputHandler = (value) => {
props.setCount(value);
};
return (
<View style={styles.searchBox}>
<Pressable style={styles.submitBtn} title="Click Me !">
<Text>☀️</Text>
</Pressable>
<TextInput
style={styles.searchInput}
placeholder="Enter Goal"
onChangeText={onInputHandler}
/>
<Pressable
style={styles.submitBtn}
title="Click Me !"
onPress={props.submitHandler}
>
<Text>🔥🔥</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
searchBox: {
flexDirection: "row",
justifyContent: "space-around",
},
searchInput: {
width: "90%",
textAlign: "center",
padding: 10,
// color: 'white',
borderRadius: 10,
borderWidth: 1,
marginHorizontal: 5,
},
submitBtn: {
color: "black",
justifyContent: "space-around",
padding: 10,
borderRadius: 10,
borderWidth: 1,
},
});
You have to return the filtered array from your onDelete function
const onDelete = (goalId) => {
props.setCourseGoal((currGoal) => {
return currGoal.filter((goal) => goal.key !== goalId);
});
};

Check the render method of `RestApi`

i got this This error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of RestApi.
This is my code App.js
import React from 'react';
import { StyleSheet } from 'react-native';
import RestApi from './x/RestApi';
export default function App() {
return (
<RestApi/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
color: 'white',
alignItems: 'center',
justifyContent: 'center',
}
})
This is my code RestApi.js
import axios from 'axios';
import React, { useState, useEffect } from 'react'
import { Button, Flatlist, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
export default function RestApi() {
const [title, setTitle] = useState("");
const [value,setValue] = useState("");
const [items, setItems] = useState([]);
const [button, setButton] = useState("Simpan");
const [selectedUser, setSelectedUser] = useState({});
const submit =()=>{
const data = {
value,title
}
//console.log(data)
if(button=="Simpan"){
axios.post('https://achmadhilmy-sanbercode.my.id/api/v1/news', data)
.then(res=>{
console.log('res: ', res)
setTitle("")
setValue("")
GetData()
}).catch(err=>{
console.log('error: ',err)
})
}else{
axios.put(`https://achmadhilmy-sanbercode.my.id/api/v1/news/${selectedUser.id}`, data)
.then(res=>{
console.log('res: ',res)
setTitle("")
setValue("")
GetData()
setButton("Simpan")
}).catch(err=>{
console.log('error: ', err)
})
}
}
const onSelectItem = (item)=>{
console.log(item)
setSelectedUser(item)
setTitle(item.title)
setValue(item.value)
setButton("Update")
}
const GetData=()=>{
axios.get('https://achmadhilmy-sanbercode.my.id/api/v1/news')
.then(res=>{
const data1 = (res.data.data)
console.log('res: ', data1)
setItems(data1)
})
}
const onDelete=(item)=>{
axios.delete(`https://achmadhilmy-sanbercode.my.id/api/v1/news/${item.id}`)
.then(res=>{
console.log('res: ', res)
GetData()
}).catch(err=>{
console.log('error: ', err)
})
}
useEffect(() => {
GetData()
}, [])
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Tampilkan Api (CRUD)</Text>
</View>
<View style={styles.content1}>
<Text>Post Data</Text>
<TextInput
placeholder="Masukan judul berita"
style={styles.input}
value={title}
onChangeText={(value)=>setTitle(value)}
/>
<TextInput
placeholder="Masukan Isi berita"
style={styles.input}
value={value}
onChangeText={(value)=>setValue(value)}
/>
<Button
title={button}
onPress={submit}
/>
</View>
<View style={styles.content1}>
<Text>Get Data Berita</Text>
<Flatlist
data={items}
keyExtractor={(item, index) => `${item.id}-${index}`}
renderItem={({item})=>{
return (
<View>
<TouchableOpacity onPress={()=>onDelete(item)}>
<Text style={{color: 'red', alignSelf: 'flex-end'}}>X</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()=>onSelectItem(item)}style={{borderRadius: 6,backgroundColor:'grey', padding: 5, marginBottom:10}}>
<Text style={{color: 'white'}}>{item.title}</Text>
<Text style={{color: 'white'}}>{item.value}</Text>
</TouchableOpacity>
</View>
)
}}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:'white'
},
header:{
paddingTop: 50,
paddingHorizontal: 16,
backgroundColor: 'grey',
alignItems: 'center'
},
title:{
color: 'white',
fontSize: 20
},
content1:{
paddingHorizontal: 16
},
input:{
borderWidth:1,
paddingVertical: 10,
paddingHorizontal: 5,
borderRadius: 6,
marginTop: 10
},
contentNews:{
backgroundColor:'grey',
paddingVertical:10
}
})
Your RestApi component does return anything, because the return statement is nested within the submit function, but that does not get called.
Could you try unnesting the return statement? See example below, where I also unnested the useEffect call and several other functions.
import axios from 'axios'
import React, { useState, useEffect } from 'react'
import {
Button,
Flatlist,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from 'react-native'
export default function RestApi() {
const [title, setTitle] = useState('')
const [value, setValue] = useState('')
const [items, setItems] = useState([])
const [button, setButton] = useState('Simpan')
const [selectedUser, setSelectedUser] = useState({})
const submit = () => {
const data = {
value,
title
}
//console.log(data)
if (button == 'Simpan') {
axios
.post('https://achmadhilmy-sanbercode.my.id/api/v1/news', data)
.then(res => {
console.log('res: ', res)
setTitle('')
setValue('')
GetData()
})
.catch(err => {
console.log('error: ', err)
})
} else {
axios
.put(
`https://achmadhilmy-sanbercode.my.id/api/v1/news/${selectedUser.id}`,
data
)
.then(res => {
console.log('res: ', res)
setTitle('')
setValue('')
GetData()
setButton('Simpan')
})
.catch(err => {
console.log('error: ', err)
})
}
}
const onSelectItem = item => {
console.log(item)
setSelectedUser(item)
setTitle(item.title)
setValue(item.value)
setButton('Update')
}
const GetData = () => {
axios
.get('https://achmadhilmy-sanbercode.my.id/api/v1/news')
.then(res => {
const data1 = res.data.data
console.log('res: ', data1)
setItems(data1)
})
}
const onDelete = item => {
axios
.delete(
`https://achmadhilmy-sanbercode.my.id/api/v1/news/${item.id}`
)
.then(res => {
console.log('res: ', res)
GetData()
})
.catch(err => {
console.log('error: ', err)
})
}
useEffect(() => {
GetData()
}, [])
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Tampilkan Api (CRUD)</Text>
</View>
<View style={styles.content1}>
<Text>Post Data</Text>
<TextInput
placeholder="Masukan judul berita"
style={styles.input}
value={title}
onChangeText={value => setTitle(value)}
/>
<TextInput
placeholder="Masukan Isi berita"
style={styles.input}
value={value}
onChangeText={value => setValue(value)}
/>
<Button title={button} onPress={submit} />
</View>
<View style={styles.content1}>
<Text>Get Data Berita</Text>
<Flatlist
data={items}
keyExtractor={(item, index) => `${item.id}-${index}`}
renderItem={({ item }) => {
return (
<View>
<TouchableOpacity
onPress={() => onDelete(item)}>
<Text
style={{
color: 'red',
alignSelf: 'flex-end'
}}>
X
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => onSelectItem(item)}
style={{
borderRadius: 6,
backgroundColor: 'grey',
padding: 5,
marginBottom: 10
}}>
<Text style={{ color: 'white' }}>
{item.title}
</Text>
<Text style={{ color: 'white' }}>
{item.value}
</Text>
</TouchableOpacity>
</View>
)
}}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white'
},
header: {
paddingTop: 50,
paddingHorizontal: 16,
backgroundColor: 'grey',
alignItems: 'center'
},
title: {
color: 'white',
fontSize: 20
},
content1: {
paddingHorizontal: 16
},
input: {
borderWidth: 1,
paddingVertical: 10,
paddingHorizontal: 5,
borderRadius: 6,
marginTop: 10
},
contentNews: {
backgroundColor: 'grey',
paddingVertical: 10
}
})

How can i get back my data list after searching by words?

i use Flatlist and search by words on renderHeader() function. I can filter but when i delete letters, i couldn't get main list again. I think there is a logic problem but i couln't find after trying something...
i've got a new one when i fixed problem. I tried to fix but i couldn't do that, i should put the problem in front of experts :)
import React, {Component, useState} from 'react'
import {
Text,
StyleSheet,
View,
FlatList,
SafeAreaView,
ScrollView,
Image,
TextInput,
} from 'react-native'
import data from '../../data'
const Flatlistexample = () => {
//main list state
let [list, setList] = useState(data);
//search state
const [search, setSearch] = useState('');
//search filter
searchFilter = text => {
// onChangeText
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}
//search function
renderHeader = () =>{
return (
<View style={styles.seachContainer}>
<TextInput
style={styles.textInput}
placeholder={'Search...'}
value={search}
onChangeText={text => {
//setStates
searchFilter(text)
setSearch(text)
}}></TextInput>
<Text
style={{
alignItems: 'flex-start',
color: 'black',
fontSize: 22,
}}>
{search}
</Text>
</View>
)
}
return (
<SafeAreaView
style={{
flex: 1,
}}>
<FlatList
data={list}
renderItem={({item, index}) => {
return (
<ScrollView>
<SafeAreaView
style={[
styles.container,
{backgroundColor: index % 2 === 0 ? '#fafafa' : '#bbb'},
]}>
<Image style={styles.profile} source={{uri: item.picture}} />
<View style={styles.rightside}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.company}>{item.company}</Text>
</View>
</SafeAreaView>
</ScrollView>
)
}}
keyExtractor={item => item._id}
//called search function
ListHeaderComponent={renderHeader()}
/>
</SafeAreaView>
)
}
export default Flatlistexample
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: 'gray',
},
profile: {
width: 50,
height: 50,
borderRadius: 25,
marginLeft: 10,
},
rightside: {
marginLeft: 20,
justifyContent: 'space-between',
marginVertical: 5,
},
name: {
fontSize: 22,
marginBottom: 10,
},
searchContainer: {
padding: 10,
borderWidth: 2,
borderColor: 'gray',
},
textInput: {
fontSize: 16,
backgroundColor: '#f9f9f9',
padding: 10,
},
})
Thanks for your help
Filter Data
onSearchText = (value) => {
this.setState({searchText: value})
if(value.trim() == "" || value == null){
this.setState({list: this.state.list}
} else {
let filter = this.state.list.fillter(data => {
// data fillter logic //
return data;
})
this.setState({filterData: filter})
}
Render FlatList
<FlatList
extradata={this.state}
data={searchText ? filterData : list}
/>
I fixed...
How?
My main data state is constant, i'm filtering on data list with filter state. So my data list doesn't change anytime.
import React, {Component, useState} from 'react'
import {
Text,
StyleSheet,
View,
FlatList,
SafeAreaView,
ScrollView,
Image,
TextInput,
} from 'react-native'
import data from '../../data'
const Flatlistexample = () => {
//main list state
let [list, setList] = useState(data)
//search state
const [search, setSearch] = useState('')
//filter state
const [updated, setUpdated] = useState(data)
//search filter
searchFilter = text => {
// onChangeText
if (text) {
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1
})
setUpdated(newData)
}
//search function
renderHeader = () => {
return (
<View style={styles.seachContainer}>
<TextInput
style={styles.textInput}
placeholder={'Search...'}
value={search}
onChangeText={text => {
searchFilter(text)
setSearch(text)
}}></TextInput>
<Text
style={{
alignItems: 'flex-start',
color: 'black',
fontSize: 22,
}}>
{search}
</Text>
</View>
)
}
return (
<SafeAreaView
style={{
flex: 1,
}}>
<FlatList
//i'm showing filter state
data={updated}
renderItem={({item, index}) => {
return (
<ScrollView>
<SafeAreaView
style={[
styles.container,
{backgroundColor: index % 2 === 0 ? '#fafafa' : '#bbb'},
]}>
<Image style={styles.profile} source={{uri: item.picture}} />
<View style={styles.rightside}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.company}>{item.company}</Text>
</View>
</SafeAreaView>
</ScrollView>
)
}}
keyExtractor={item => item._id}
//called search function
ListHeaderComponent={renderHeader()}
/>
</SafeAreaView>
)
}
export default Flatlistexample
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderColor: 'gray',
},
profile: {
width: 50,
height: 50,
borderRadius: 25,
marginLeft: 10,
},
rightside: {
marginLeft: 20,
justifyContent: 'space-between',
marginVertical: 5,
},
name: {
fontSize: 22,
marginBottom: 10,
},
searchContainer: {
padding: 10,
borderWidth: 2,
borderColor: 'gray',
},
textInput: {
fontSize: 16,
backgroundColor: '#f9f9f9',
padding: 10,
},
})
/*
else if(text.length > uzunluk){
setList(data)
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}else if(text.length<uzunluk){
setList(data)
const newData = list.filter(item => {
const listItem = `${item.name.toLowerCase()} ${item.company.toLowerCase()}`
return listItem.indexOf(text.toLowerCase()) > -1;
})
setList(newData)
}
*/

When putting new value into an input field erases a previous one

With my current code, I have two input fields and a drop down menu. When ever a value is placed into the field or modified, it clears the rest of the fields. The only one that will stay consistent is the drop down menu. I have suspicions that my useEffect hooks may be doing something, but I'm quite unsure of why. Any suggestions would be great.
(FYI: storeArtic is the push to firebase)
CustomScreen.js
import React, { useState } from "react";
import { StyleSheet, Text, Keyboard, View, TouchableWithoutFeedback } from "react-native";
import { Button, Input } from "react-native-elements";
import { Dropdown } from "react-native-material-dropdown";
import { storeArtic } from '../helpers/fb-settings';
const CustomScreen = ({ route, navigation }) =>{
//create a screen with the ability to add a picture with text to the deck of artic cards
//add check box solution for selection of word type (maybe bubbles, ask about this)
const articDrop = [
{value: 'CV'},
{value: 'VC'},
{value: 'VV'},
{value: 'VCV'},
{value: 'CVCV'},
{value: 'C1V1C1V2'},
{value: 'C1V1C2V2'},
];
const [articCard, setCard] = useState({
word: '',
imageUrl: '',
aType:'',
cType: '',
mastery: false
})
return(
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View>
<Text>Please enter the information of your custom card!</Text>
<Input
placeholder="Enter valid image url"
value={articCard.imageUrl}
autoCorrect={false}
onChangeText={(val) => setCard({ imageUrl: val })}
/>
<Input
placeholder="Enter word or phrase"
value={articCard.word}
autoCorrect={false}
onChangeText={(val) =>
setCard({ word: val, aType: val.charAt(0).toUpperCase(), mastery: false})
}
/>
<Dropdown
value={articCard.cType}
onChangeText={(text) => setCard({cType: text})}
label="Artic Type"
data={articDrop}
/>
<Button
//this will save the cards to the database
title="Save"
onPress={() => {
storeArtic({articCard})
}}
/>
<Button
title="Clear"
onPress={() => {
setCard({word: '', aType: '', cType: '', imageUrl: '', mastery: false});
navigation.navigate('Home');
}}
/>
</View>
</TouchableWithoutFeedback>
)
}
export default CustomScreen;
HomeScreen.js
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 [ initialDeck, setInitialDeck] = useState([]);
useEffect(() => {
try {
initArticDB();
} catch (err) {
console.log(err);
}
setupArticListener((items) => {
setInitialDeck(items);
});
}, []);
useEffect(() => {
if(route.params?.articCard){
setCard({imageUrl: state.imageUrl, word: state.word, aType: state.aType, cType: state.cType, mastery: state.mastery})
}
}, [route.params?.articType] );
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: initialDeck})}
/>
<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;
Unlike class based setState, with functional components when you do setState, it will override the state with what you provide inside setState function. It is our responsibility to amend state (not overrite)
So, if your state is an object, use callback approach and spread previous state and then update new state.
Like this
<Input
placeholder="Enter valid image url"
value={articCard.imageUrl}
autoCorrect={false}
onChangeText={(val) => setCard(prev => ({ ...prev, imageUrl: val }))} //<----- like this
/>
Do the same for all your inputs.

Categories

Resources