AsyncStorage not finding variable - react-native

I'm sure its a stupid mistake somewhere but when I switch between class component to functional (to learn/understand how state works in both of these) I kind of miss the logic sometimes (with this.props etc). (home.js navigates to the page called addDiary.js)
I'm not finished with the async logic/code but don't understand why I get the error "cant find variable: diary" at this point, thank you
Home.js
const Home = ({navigation}) => {
const [refreshing, setRefreshing] = useState(false);
const [diary, setDiary] = useState(null)
whenRefresh = async () => {
try{
setRefreshing(true);
const diary = await AsyncStorage.getItem('diary')
setDiary(JSON.parse('diary'))
setRefreshing(false)}
catch (error) {console.log(error)}
}
return(
<View style={styles.home}>
<ScrollView
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={whenRefresh}/>}
style={styles.body}>
{diary ? <ListItem
title={diary.title}
subtitle="test"
onPress={()=>{console.log("listitem pressed")}}
/> : null}
addDiary.js
const AddDiary = () => {
const [title, setTitle] = useState()
const [body, setBody] = useState()
const submit = async () => {
const diary = {title, body}
await AsyncStorage.setItem('diary', JSON.stringify(diary))
navigation.goBack()
}
return(
<SafeAreaView style={styles.home}>
<View style={styles.group}>
<Text style={styles.label}>Title:</Text>
<TextInput
placeholder="title"
style={styles.titleInput}
onChangeText={setTitle}
value={title}
/>
</View>
<View style={[styles.group, {flex:1}]}>
<Text style={styles.label}>Body:</Text>
<TextInput
placeholder="title"
style={[styles.titleInput, {height: 300}]}
onChangeText={setBody}
value={body}
/>
</View>
<Button
name="check-circle"
size={50}
color="black"
onPress={submit}
/>
</SafeAreaView>
)
}

const submit = async () => {
const diary = {title, body}
await AsyncStorage.setItem('diary',JSON.stringify(diary))
}
Change your submit function to this.
and it should work fine
const Home = ({navigation}) => {
const [refreshing, setRefreshing] = useState(false);
const [diary, setDiary] = useState(null)
whenRefresh = async () => {
setRefreshing(true);
const diary = await AsyncStorage.getItem('diary')
setDiary(JSON.parse('diary'))
setRefreshing(false)
}
return(
<View style={styles.home}>
<ScrollView
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={whenRefresh}/>}
style={styles.body}>
{diary ? <ListItem
title={diary.title}
subtitle="test"
onPress={()=>{console.log("listitem pressed")}}
/> : null}

Related

Change state of RenderItem on screenLeave

Does anyone know how I can change the state of a renderItem when it leaves screen? Below I have the Flatlist with uses an Item, I want to change the state of the item once it exits the renderview.
const Item = memo(({content}) => {
const [outOfView, setOutOfView] = useState(false)
const onScroll= () => {
if (!outOfView) setOutOfView(true) //Trying to get this to work
}
return (
<View style={styles.item} onScroll={onScroll}>
<Text>{content.title}</Text>
</View>
)
})
const Slider = props => {
const flatList = useRef()
const _renderItem = ({ item, index }) => <Item content={item} />
return (
<View style={styles.container} >
{props.header ? <AppText style={styles.header} text={props.header} /> : null}
<FlatList
data={props.data}
horizontal
pagingEnabled
renderItem={_renderItem}
keyExtractor={item => item._id}
ref={flatList}
/>
</View>
)
}
YOu can do something like this
import { useIsFocused } from '#react-navigation/native';
const Item = memo(({content}) => {
const [outOfView, setOutOfView] = useState(false)
const onScroll= () => {
if (!outOfView) setOutOfView(true) //Trying to get this to work
}
const isFocused = useIsFocused();
return (
<View style={styles.item} onScroll={onScroll}>
<Text>{isFocused?content.title:"Offline"}</Text>
</View>
)
})
hope it helps. feel free for doubts

React Native - Can't find variable - conditional

I'm making an app that looks for a data in the Firebase database, and if the data exists it appears a Text Input. If the data doesn't exist, it shows another Text Input.
//CODE
function Veic({ navigation, route }) {
const [date, setDate] = useState("");
const database = firebase.firestore()
const [selectedValue, setSelectedValue] = useState("");
const [placa, setPlaca] = useState("");
const [atv, setAtv] = useState("");
const [km, setKm] = useState("");
const [obs, setObs] = useState("");
const [kmF, setKmF] = React.useState("");
const { idUser, user, uid } = route.params;
var auth = firebase.auth();
useEffect(() => { // the rest of the code doesn't read the "values_id"
const DocVeic = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(DocVeic).then((querySnapshot) => {
let values_id = null;
querySnapshot.forEach((doc) => {
values_id = doc.id;
console.log(`${values_id}`);
})
})
},[])
function altInfo(){
const Doc = query(collection(database, "user_veic"),where("email", "==", auth.currentUser?.email),where("kmF", "==", ""));
getDocs(Doc).then((querySnapshot) => {
let values = null;
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data()}`);
values = doc.id;
});
var transactionUpdate = database.collection("user_veic").doc(values);
transactionUpdate.update({
kmF: kmF,
})
})
}
// ADD A DATA
function addInfo(){
database.collection("user_veic").add({
email: auth.currentUser?.email,
placa: placa,
atv: atv,
km: km,
obs: obs,
dataInicial: data_full,
dataFinal: '',
kmF: '',
});
navigation.navigate('Liber', {idUser: user})
}
return (
<View style={fundoVeic.container}>
<View style={fundoVeic.perfilUser}>
<Text style={{color:'#007831',fontWeight:'bold',fontSize:15,height: 40}}>
<Image style={fundoVeic.imageEnvel} source={require('../../imagens/envelope.png')}/>
<Text style={{color:'#cce4d5'}}>...</Text>{auth.currentUser?.email}
</Text>
</View>
{values_id === null ?
<View>
<TextInput
style={fundoVeic.input}
placeholder='Digite a placa do veículo'
maxLength={7}
placeholderTextColor='#000'
onChangeText={txtPlaca => setPlaca(txtPlaca)}
value={placa}
/>
<TextInput
style={fundoVeic.input}
placeholder='Digite a atividade'
placeholderTextColor='#000'
onChangeText={txtAtv => setAtv(txtAtv)}
value={atv}
/>
<TextInput
style={fundoVeic.input}
keyboardType='numeric'
placeholder='Digite o km do veículo'
placeholderTextColor='#000'
onChangeText={txtKm => setKm(txtKm)}
value={km}
/>
<TextInput
style={fundoVeic.inputObs}
multiline={true}
numberOfLines={5}
placeholder='Observação (opcional)'
placeholderTextColor='#000'
onChangeText={txtObs => setObs(txtObs)}
value={obs}
/>
<Pressable
style={fundoVeic.button}
onPress={addInfo}
>
<Text style={fundoVeic.textButton}>Selecionar</Text>
</Pressable>
</View>
:
<View>
<TextInput
keyboardType='numeric'
placeholder='Digite o km final do veículo'
placeholderTextColor='#000'
onChangeText={txtKmF => setKmF(txtKmF)}
value={kmF}
/>
<Pressable
onPress={altInfo}
>
<Text>Liberar</Text>
</Pressable>
</View>
}
</View>
);
}
export default Veic;
The app has a login. When logging in, enters a screen that will appear a certain text and input (with a condition). The condition: if the variable "kmf", in Firebase, is empty, it shows an input on the screen for the user to put a km. When the user writes the km, the data is updated. The problem is that I am not able to make a condition that reads the "values_id". What is the solution?
values_id is not component state. In fact the variable only exists inside the useEffect function and is not available anywhere else. Add it to the component state with useState.
const [valuesId, setValuesId] = useState<string>(null);
useEffect(() => {
// ...
setValuesId(doc.id);
},[])

how to refresh the list after submitting a form in react-native?

when redirecting to index screen after submitting a post-form, the index screen does not show the newly added item in the list, can anyone help?
here is my Customer.js page
export default function Customer({ navigation }) {
const [customers, setCustomers] = useState([]);
const [isLoading, setLoading] = useState(true);
const getCustomers = async () => {
try {
const response = await fetch("http://localhost:3001/api/customers");
const json = await response.json();
setCustomers(json);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
getCustomers();
}, []);
return (
<View style={styles.item}>
<TouchableOpacity
onPress={() => navigation.navigate("AddCustomer")}
style={styles.btn}
>
<Text style={styles.btnText}>Add New Customer</Text>
</TouchableOpacity>
<FlatList
data={customers}
extraData={customers}
renderItem={({ item }) => (
<TouchableOpacity
onPress={() => navigation.navigate("CustomerDetails", item)}
>
<Text style={styles.item}>{item.name}</Text>
</TouchableOpacity>
)}
keyExtractor={(item) => item._id}
/>
</View>
);
}
}
and here is my AddCustomer.js page
const AddCustomer = ({ navigation, route }) => {
const [name, setName] = useState("");
const [phone, setPhone] = useState(0);
const [isGold, setIsGold] = useState(false);
const handleSubmit = async () => {
// e.preventDefault();
return await fetch("http://localhost:3001/api/customers", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
phone: phone,
isGold: isGold,
}),
}).then(() => {
navigation.navigate("Customer", { customers: [name, phone, isGold] });
});
};
return (
<View>
<Text style={styles.title}>Add New Customer</Text>
<View>
<TextInput
style={styles.input}
onChangeText={(val) => setName(val)}
value={name}
placeholder="Your name"
onBlur={Keyboard.dismiss}
/>
<TextInput
style={styles.input}
onChangeText={(val) => setPhone(val)}
value={phone}
placeholder="phone number"
/>
<TextInput
style={styles.input}
onChangeText={(val) => setIsGold(val)}
value={isGold}
placeholder="is gold member"
autoCorrect={false}
autoCapitalize={false}
/>
</View>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton} onPress={handleSubmit}>
<Text style={styles.saveButtonText}>Add Customer</Text>
</TouchableOpacity>
</View>
</View>
);
};
new customer would be added and everything else work fine but the Customer page does not get re-rendered or refresh or reload.
In your Customer.js do it like below -
useEffect(() => {
const unsubscribe = navigation.addListener('focus', async () => {
getCustomers();
});
return unsubscribe ;
}, [navigation]);
import { useFocusEffect } from '#react-navigation/native';
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
getCustomers();
return () => {
// Do something when the screen is unfocused
};
}, []),
);

How to get the current theme in ui-kitten react native, i.e. whether the current theme is dark or light?

I am trying to change the background color of my react native app based on the current theme, i.e., whether it is dark or light.
Here is my code :
const SignUp = ({navigation}) => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
const [secureTextEntry, setSecureTextEntry] = useState(true);
const [error, setError] = useState("")
const clear = () => {
setEmail('')
setPassword('')
setName('')
setError('')
}
function onLinkClick(){
navigation.navigate('login')
clear()
}
async function onButtonPress() {
if(email && password && name){
setError("");
await auth().createUserWithEmailAndPassword(email, password)
.then(() => {
const {currentUser} = auth();
firestore().
collection(`users/${currentUser.uid}/name`)
.add({
name: name
})
clear()
navigation.navigate('login')
})
.catch(() => {
setError("Email already exists!!! Login instead.")
})
}else{
setError("Please fill all the fields");
}
}
var colour = '#1d2447'
const toggleSecureEntry = () => {
if(password){
setSecureTextEntry(!secureTextEntry);
}
};
const renderIcon = (props) => (
<TouchableWithoutFeedback onPress={toggleSecureEntry}>
<Icon {...props} name={secureTextEntry ? 'eye-off' : 'eye'}/>
</TouchableWithoutFeedback>
);
return(
<React.Fragment>
<View style={[styles.containerStyle, {backgroundColor: `${colour}`}]}>
<Text style={styles.textStyle} category='h2'>What should we call</Text>
<Text style={[styles.textStyle, {marginBottom: 10}]} category='h2'>you?</Text>
<Text style={styles.subtextStyle}>You'll need a name to make your</Text>
<Text style={styles.subtextStyle}>own posts, customize your blog,</Text>
<Text style={styles.subtextStyle}>and message people</Text>
<View style={styles.formStyle}>
<Input
style={styles.textInputStyle}
size='large'
placeholder='Email'
value={email}
onChangeText={nextValue => setEmail(nextValue)}
/>
<Input
value={password}
placeholder='Password'
accessoryRight={renderIcon}
secureTextEntry={secureTextEntry}
onChangeText={nextValue => setPassword(nextValue)}
style={styles.textInputStyle}
size="large"
autoCorrect
/>
<Input
value={name}
placeholder='Name'
onChangeText={nextValue => setName(nextValue)}
style={styles.textInputStyle}
size="large"
/>
</View>
<Button style={styles.button} size='medium' status='basic' appearance="outline" onPress={onButtonPress}>Sign Up</Button>
<Text style={styles.errorTextStyle} category='h6'>{error}</Text>
<Text style={styles.linkStyle}>Already have an account?</Text>
<Text style={styles.linkStyle} onPress={() => onLinkClick()}>Login</Text>
</View>
</React.Fragment>
)
Here I want to change the background depending on whether the current theme is dark or light, but I'm not able to fetch it.

React Native Function Component ASYNC / AWAIT Problem

sorry for bad English.
My function component not waiting API Function, I'm write async and await and not working again..
"Object are not valid as a React child" error screen...
Please help me :'/
const NormalCarousel = async (props) => {
const navigation = useNavigation();
const [ResponseData, setResponseData] = useState('');
const ComponentAPI = props.api;
const API = await axios.get(ComponentAPI).catch((error) => {alert(error)});
await setResponseData(API);
return(
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
{
ResponseData.map(item => (
<TouchableOpacity style={styles.CarouselTouchable} onPress={() => navigation.navigate("Ürün", {id: item.item_id})}>
<Image
style={styles.CarouselImage}
source={{uri: item?.item_avatar}}
/>
<View style={styles.CarouselView}>
<Text style={styles.CarouselTitle}>{item?.item_name}</Text>
<Text style={styles.CarouselSubtitle}>{item?.item_stock_code}</Text>
</View>
</TouchableOpacity>
))
}
</ScrollView>
)
}
The error is happening because the parent component trying to render this component is actually rendering a Promise which resolves into a component. That's not possible.
You should instead call the function to load the data once on component mount (useEffect). You'll also need to replace useState('') with useState([]) since you're trying to map over this data when rendering.
const NormalCarousel = (props) => {
const { api } = props;
const navigation = useNavigation();
const [responseData, setResponseData] = useState([]);
useEffect(() => {
getAPI();
}, []);
async function getAPI() {
const API = await axios.get(api).catch((error) => alert(error));
setResponseData(API);
}
return(
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
{
responseData.map(item => (
<TouchableOpacity style={styles.CarouselTouchable} onPress={() => navigation.navigate("Ürün", {id: item.item_id})}>
<Image
style={styles.CarouselImage}
source={{uri: item.item_avatar}}
/>
<View style={styles.CarouselView}>
<Text style={styles.CarouselTitle}>{item.item_name}</Text>
<Text style={styles.CarouselSubtitle}>{item.item_stock_code}</Text>
</View>
</TouchableOpacity>
))
}
</ScrollView>
)
}