Firestore "get" function getting executed multiple times - javascript

I'm a newbie at React-Native and Firebase and i'm using Firebase Cloud Firestore for a project. I'm trying to get filtered data from the database statically (as i'm learning to use it for now), but somehow my function is getting executed multiple times, the numbers of readings is increasing rapidly and i'm having some random errors too. I would like to know what's wrong.
Here is my code for the file that only deals with the database (Firestore.js):
import React, { useState, useEffect } from "react";
import { ActivityIndicator } from "react-native";
import * as firebase from "firebase";
import "firebase/firestore";
function onResult(QuerySnapshot) {
console.log("Pegamos a coleção de Animais.");
}
function onError(error) {
console.error(error);
}
export function GetAnimalsByEspecie(especie) {
const [loading, setLoading] = useState(true);
const [animais, setAnimais] = useState([]);
console.log("entrou Especie");
const subscriber = firebase
.firestore()
.collection("Animal")
.where("especie", "==", especie)
.get()
.then((querySnapshot) => {
const animaisList = [];
querySnapshot.forEach((documentSnapshot) => {
animaisList.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setAnimais(animaisList);
setLoading(false);
});
if (loading) {
console.log("loading");
return <ActivityIndicator />;
}
return animais;
}
export function GetAnimalsByNome(nomeAnimal) {
const [loading, setLoading] = useState(true);
const [animais, setAnimais] = useState([]);
console.log("entrou nome nooome");
const subscriber = firebase
.firestore()
.collection("Animal")
.where("nome", "==", nomeAnimal)
.get()
.then((querySnapshot) => {
const animaisList = [];
querySnapshot.forEach((documentSnapshot) => {
animaisList.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setAnimais(animaisList);
setLoading(false);
});
if (loading) {
console.log("loading");
return <ActivityIndicator />;
}
return animais;
}
export default function GetAnimals() {
const [loading, setLoading] = useState(true);
const [animais, setAnimais] = useState([]);
useEffect(() => {
console.log("entrou listener");
const subscriber = firebase
.firestore()
.collection("Animal")
// .where('')
.onSnapshot((querySnapshot) => {
const animaisList = [];
querySnapshot.forEach((documentSnapshot) => {
animaisList.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setAnimais(animaisList);
setLoading(false);
});
return () => subscriber();
}, []);
if (loading) {
console.log("loading");
return <ActivityIndicator />;
}
return animais;
}
Here is my code for the file that displays data on the screen (index.js):
import React, { useState } from "react";
import {
View,
Text,
KeyboardAvoidingView,
StyleSheet,
Image,
TextInput,
TouchableHighlight,
ScrollView,
Button,
ActivityIndicator,
FlatList,
} from "react-native";
import { SearchBar } from "react-native-elements";
import { createStackNavigator } from "#react-navigation/stack";
import { SafeAreaView } from "react-native-safe-area-context";
import SubmitButton from "../../shared/SubmitButton";
import FocusAwareStatusBar from "../../shared/StatusBar";
import GetAnimals, {GetAnimalsByEspecie, GetAnimalsByNome} from "../../db/Firestore";
const styles = StyleSheet.create({
background: {
flex: 1,
backgroundColor: "#fafafa",
alignItems: "center",
justifyContent: "center",
},
regform: {
alignSelf: "stretch",
},
textInput: {
fontFamily: "Roboto_400Regular",
fontSize: 14,
alignSelf: "stretch",
paddingLeft: 12,
marginHorizontal: 16,
color: "#000000",
borderBottomColor: "#dcdcdc",
borderBottomWidth: 0.8,
paddingBottom: 8,
},
label: {
alignSelf: "stretch",
marginTop: 28,
marginBottom: 32,
paddingLeft: 28,
color: "#589b9b",
},
container: {
flex: 1,
justifyContent: "center",
alignSelf: "center",
height: 128,
width: 128,
backgroundColor: "#fff",
elevation: 4,
},
button: {
alignItems: "center",
backgroundColor: "#f1f2f2",
paddingTop: 44,
paddingBottom: 48,
},
infobox: {
backgroundColor: "#cfe9e5",
borderRadius: 4,
height: 80,
width: 328,
marginTop: 16,
marginHorizontal: 16,
justifyContent: "space-evenly",
alignContent: "center",
},
infotext: {
fontFamily: "Roboto_400Regular",
fontSize: 14,
color: "#434343",
paddingHorizontal: 15,
marginVertical: 11,
textAlign: "center",
},
});
export default function Animais() {
var animais = GetAnimalsByEspecie('shitzu');
const search = () => {
const [searchQuery, setSearchQuery] = useState("");
return (
<SearchBar
placeholder="Escreva aqui..."
onChangeText={""}
value={searchQuery}
/>)
};
return (
<SafeAreaView style={{ flex: 1 }}>
<FocusAwareStatusBar barStyle="light-content" backgroundColor="#88c9bf" />
<KeyboardAvoidingView style={styles.background}>
<View>
<Text>Animais</Text>
<FlatList
ListHeaderComponent={''}
data={animais}
renderItem={({ item }) => (
<View
style={{
height: 50,
width: 350,
flex: 1,
alignItems: "center",
justifyContent: "center",
}}
>
<Text>Animal ID: {item.id}</Text>
<Text>Animal Name: {item.nome}</Text>
</View>
)}
/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
I'm not using SearchBar yet, for now i'm just trying to fetch and display the data which have 'especies' field equal to 'shitzu' from the database. Sometimes I get the correct information, sometimes I get errors.
Thanks for the help.

You should put your fetches inside of a useEffect so you can make it run only once. Otherwise, when your fetch callbacks set state, you'll get a re-render, and your fetch code will run again. Also, it looks like GetAnimalsByEspecie, since it invokes hooks, should itself be a hook. For example:
export function useAnimalsByEspecie(especie) {
const [loading, setLoading] = useState(true);
const [animais, setAnimais] = useState([]);
useEffect(() => {
const subscriber = firebase
.firestore()
.collection("Animal")
.where("especie", "==", especie)
.get()
.then((querySnapshot) => {
const animaisList = [];
querySnapshot.forEach((documentSnapshot) => {
animaisList.push({
...documentSnapshot.data(),
key: documentSnapshot.id,
});
});
setAnimais(animaisList);
setLoading(false);
});
}, [especie]);
return [animais, loading];
}
...which would be used like:
function Animais() {
var [animais, isLoading] = useAnimalsByEspecie('shitzu');
const search = () => {
const [searchQuery, setSearchQuery] = useState("");
return (
<SearchBar
placeholder="Escreva aqui..."
onChangeText={""}
value={searchQuery}
/>)
};
if (isLoading) {
return <ActivityIndicator />;
}
return (
<SafeAreaView style={{ flex: 1 }}>
<FocusAwareStatusBar barStyle="light-content" backgroundColor="#88c9bf" />
<KeyboardAvoidingView style={styles.background}>
<View>
<Text>Animais</Text>
<FlatList
ListHeaderComponent={''}
data={animais}
renderItem={({ item }) => (
<View
style={{
height: 50,
width: 350,
flex: 1,
alignItems: "center",
justifyContent: "center",
}}
>
<Text>Animal ID: {item.id}</Text>
<Text>Animal Name: {item.nome}</Text>
</View>
)}
/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
}

Related

Why my camera is not taking photos? expo-camera

Why my camera is not taking photos? expo-camera? when I test this in my emulator android then it was taking photos and logging its value but when i test and try to take a photo on a real device android then it was not taking photos and not logging any value does anyone knows how can I fix this problem to make this work? my camera permission is granted
import { Camera } from 'expo-camera';
import { TouchableOpacity, Text, View } from 'react-native';
import { useState, useEffect, useRef } from "react";
import { firebase } from '../../Storage/Firebase/config';
export default function CameraPage({ navigation }) {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.front);
const cameraRef = useRef(null);
useEffect(() => {
(async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
const handleTakePicture = async () => {
if (cameraRef.current) {
const photo = await cameraRef.current.takePictureAsync();
if (!photo.cancelled) {
const response = await fetch(photo.uri);
const blob = await response.blob();
const filename = photo.uri.substring(photo.uri.lastIndexOf('/') + 1);
const ref = firebase.storage().ref().child(filename);
const snapshot = await ref.put(blob);
const url = await snapshot.ref.getDownloadURL();
console.log(url)
navigation.navigate('addpost', { post: url });
}
}
}
return (
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type} ref={cameraRef}>
<View style={{ flex: 1, backgroundColor: 'transparent', flexDirection: 'row' }}>
<TouchableOpacity
style={{
alignSelf: 'center',
alignItems: 'center',
width: 90,
height: 90,
borderRadius: 500,
backgroundColor: 'transparent',
marginTop: '150%',
marginLeft: '35%',
borderColor: '#fff',
borderWidth: 4,
}}
onPress={handleTakePicture}
>
<View style={{ opacity: 0.5, }} />
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
import { Camera, Permissions } from 'expo-camera';
import { TouchableOpacity, Text, View } from 'react-native';
import { useState, useEffect, useRef } from "react";
import { firebase } from '../../Storage/Firebase/config';
export default function CameraPage({ navigation }) {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.front);
const cameraRef = useRef(null);
useEffect(() => {
(async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return (
<View>
<Text>No access to camera</Text>
<Button title='Grant Permission' onPress={getPermission} />
</View>
);
}
const handleTakePicture = async () => {
if (cameraRef.current) {
const photo = await cameraRef.current.takePictureAsync();
if (!photo.cancelled) {
const response = await fetch(photo.uri);
const blob = await response.blob();
const filename = photo.uri.substring(photo.uri.lastIndexOf('/') + 1);
const ref = firebase.storage().ref().child(filename);
const snapshot = await ref.put(blob);
const url = await snapshot.ref.getDownloadURL();
console.log(url)
navigation.navigate('addpost', { post: url });
}
}
}
const getPermission = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
setHasPermission(status === 'granted');
}
return (
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type} ref={cameraRef}>
<View style={{ flex: 1, backgroundColor: 'transparent', flexDirection: 'row' }}>
<TouchableOpacity
style={{
alignSelf: 'center',
alignItems: 'center',
width: 90,
height: 90,
borderRadius: 500,
backgroundColor: 'transparent',
marginTop: '150%',
marginLeft: '35%',
borderColor: '#fff',
borderWidth: 4,
}}
onPress={handleTakePicture}
>
<View style={{ opacity: 0.5, }} />
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
Also, Make sure that the app has been granted the necessary permissions to access the camera on the device. You can check this by going to the device's settings and verifying that the app has been granted camera permissions.

How to customise Webview to navigate website using back button in React Native and exit app by pressing back twice?

I am facing issues in implementing Webview navigation of website using back button as back button when pressed exits the app.
I implemented a button functionality that uses the browser functionality of going back to the previous page and next page. But, this was not an effective implementation.
Here's my webview code:
import React, { useEffect, useState, useRef } from "react";
import {
View,
Text,
StyleSheet,
SafeAreaView,
StatusBar,
Alert,
BackHandler,
} from "react-native";
import { State, TouchableOpacity } from "react-native-gesture-handler";
import * as firebase from "firebase";
import { loggingOut } from "../API/firebaseMethods";
import { WebView } from "react-native-webview";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import SignIn from "./SignIn";
import SignUp from "./SignUp";
import { useBackHandler } from "#react-native-community/hooks";
import NavigationView from "./NavigationView";
const Tab = createBottomTabNavigator();
const LENNY = "https://www.testbooking.lennyconsulting.com/";
const THEME_COLOR = "#000000";
export default function Dashboard({ navigation }) {
function backActionHandler() {
Alert.alert("", "Are Your Sure To Exit The App?", [
{
text: "No",
onPress: () => null,
style: "cancel",
},
{
text: "Yes",
onPress: () => BackHandler.exitApp(),
},
]);
return true;
}
useBackHandler(backActionHandler);
let currentUserUID = firebase.auth().currentUser.uid;
const [firstName, setFirstName] = useState("");
useEffect(() => {
async function getUserInfo() {
try {
let doc = await firebase
.firestore()
.collection("users")
.doc(currentUserUID)
.get();
if (!doc.exists) {
Alert.alert("No user data found!");
} else {
let dataObj = doc.data();
setFirstName(dataObj.firstName);
}
} catch (err) {
Alert.alert("There is an error.", err.message);
}
}
getUserInfo();
});
const handlePress = () => {
loggingOut();
navigation.replace("Home");
};
const AppStatusBar = ({ backgroundColor, ...props }) => {
return (
<View style={[styles.statusBar, backgroundColor]}>
<StatusBar backgroundColor={backgroundColor} {...props} />
</View>
);
};
const BAR_HEIGHT = StatusBar.currentHeight;
const styles = StyleSheet.create({
statusBar: {
height: BAR_HEIGHT,
},
});
const webViewRef = useRef();
const [canGoBack, setCanGoBack] = useState(false);
const [canGoForward, setCanGoForward] = useState(false);
const handleBackPress = () => {
webViewRef.current.goBack();
};
const handleForwardPress = () => {
webViewRef.current.goForward();
};
return (
<SafeAreaView style={styles.container}>
<SafeAreaView style={{ width: "100%", height: "100%" }}>
<WebView
ref={webViewRef}
source={{ uri: LENNY }}
onLoad={console.log("Loaded")}
onNavigationStateChange={(state) => {
const back = state.canGoBack;
const forward = state.canGoForward;
setCanGoBack(back);
setCanGoForward(forward);
}}
/>
<NavigationView
onBackPress={handleBackPress}
onForwardPress={handleForwardPress}
canGoBack={canGoBack}
canGoForward={canGoForward}
/>
<StatusBar style="auto" />
<View>
<Text style={styles.text}>Hi {firstName}</Text>
<TouchableOpacity style={styles.button} onPress={handlePress}>
<Text style={styles.buttonText}>Log Out</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
<SafeAreaView style={styles.topSafeArea} />
<SafeAreaView style={styles.bottomSafeArea}>
<AppStatusBar backgroundColor={THEME_COLOR} barStyle="light-content" />
</SafeAreaView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
topSafeArea: {
flex: 1,
backgroundColor: THEME_COLOR,
},
bottomSafeArea: {
flex: 1,
backgroundColor: THEME_COLOR,
},
button: {
width: 150,
padding: 5,
backgroundColor: "#ff9999",
borderWidth: 2,
borderColor: "white",
borderRadius: 15,
alignSelf: "center",
},
buttonText: {
fontSize: 20,
color: "white",
fontWeight: "bold",
textAlign: "center",
},
container: {
height: "100%",
width: "100%",
backgroundColor: "#3FC5AB",
alignItems: "center",
justifyContent: "center",
},
text: {
textAlign: "center",
fontSize: 20,
fontStyle: "italic",
marginTop: "2%",
marginBottom: "10%",
fontWeight: "bold",
color: "black",
},
titleText: {
textAlign: "center",
fontSize: 30,
fontWeight: "bold",
color: "#2E6194",
},
});
Please someone help me. I am new to React Native.

Integrating Deso Identity into React Native App - retrieve user data from Deso Identity API call

I'm new to React Native and currently trying to integrate Deso Identity into my React Native App.
Question: How should I retrieve user data if I use WebView and what is the correct implementation to generate derived key?
Goal:
Navigate to Deso Identity Page when clicking on a button from LogIn screen
Receive derived key and all user response data after logging in
What I have tried:
I'm currently trying to generate derive key by making a call to Deso's window API without using WebView
I have tried using WebView with a DesoLogin.js component below but there's not much details from Deso's documentation and I was not able to retrieve response data after logging in
DesoLogin.js
import React, { useState, useEffect } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useNavigation } from '#react-navigation/native';
import Home from '../screens/Home';
const DesoLogin = () =>{
const navigation = useNavigation();
// const webView = WebView();
const [signIn, setSignIn] = useState(false)
const [userProfile, setUserProfile] = useState(null)
// function onMessage(data) {
// alert(data.nativeEvent.data);
// }
// const handleLogin = (e) => {
// const data = webView.getUrl(e);
// setUserProfile(data)
// }
const handleNavigationStateChange = () => {
navigation.navigate("Home", {userProfile});
}
const onNavigationStateChange = e => {
if (userProfile!==e.url) {
console.log(e.url);
setUserProfile(e.url);
console.log(userProfile);
}
};
useEffect(() => {
setSignIn(true);
if (userProfile) {
handleNavigationStateChange();
}
},[userProfile])
return (
<SafeAreaView style={{ flex: 1 }}>
<WebView
source={{
uri: 'https://identity.deso.org/derive?callback=auth://derive'
}}
// onMessage={onMessage}s
// injectedJavaScript={handleLogin}
onNavigationStateChange={onNavigationStateChange}
javaScriptEnabled
style={{ marginTop: 20 }}
/>
</SafeAreaView>
);
}
export default DesoLogin;
Error:
I know that windows.open() doesn't work in react native like it does in web application
Deso Mobile Integration Doc
Window API-Callbacks section
Login.js Screen code below
import React, { useEffect, useState } from "react";
import { useNavigation } from "#react-navigation/native";
import axios from 'axios';
import DesoLogin from "../components/DesoLogin";
import DesoIdentity from "../libs/DesoIdentity";
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'
import { COLORS, FONTS, SIZES, SHADOWS, assets } from "../constants";
import { CircleButton, RectButton, DetailsDesc, DetailsBid, FocusedStatusBar } from "../components";
const LogIn = () => {
const [loading, setLoading] = useState(null);
const [error, setError] = useState(null);
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [publicKey, setSetPublicKey] = useState(null)
const [desoIdentity, setDesoIdentity] = useState(null)
const navigation = useNavigation()
useEffect(() => {
axios('https://identity.deso.org/derive?callback=auth://derive')
.then(response => {
setSetPublicKey(response.accessSignature)
})
.catch(error => {
console.error("Error Fetching data", error);
setError(error);
throw error;
})
} , [])
const handleSignUp = () => {
return 0;
}
const handleLogin = async () => {
setSetPublicKey(publicKey);
setLoggedIn(true);
}
const handleLogout = () => {
setSetPublicKey(null);
setLoggedIn(false);
}
return (
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<TextInput
placeholder="Email"
value={email}
onChangeText={text => setEmail(text)}
style={styles.input}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={text => setPassword(text)}
style={styles.input}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={handleLogin}
style={styles.button}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
// onPress={handleSignUp}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default LogIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: COLORS.white,
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#0782F9',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: COLORS.white,
marginTop: 5,
borderColor: '#0782F9',
borderWidth: 2,
},
buttonText: {
color: COLORS.white,
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#0782F9',
fontWeight: '700',
fontSize: 16,
},
})

React Native Expo: Barcodescanner camera doesn't rotate when i press the rotate button

I'm using React Native Expo. Currently i'm trying to make an application which uses a barcodescanner for scanning QR-code objects. I've implemented a turn camera button for the front or back camera but when i press the button it does nothing only when i switch from one screen to the other. I think there is something wrong with refreshing the screen immediately but i've no clue of how i should solve this problem
Code:
import React, { useEffect, useState, useLayoutEffect } from 'react';
import { StyleSheet, Text, View, Button, Alert, ActivityIndicator, Pressable } from 'react-native';
import { globalStyles } from '../styles/global';
// import { Camera, BarCodeScanningResult } from 'expo-camera';
import { BarCodeScanner } from 'expo-barcode-scanner';
import BarcodeMask from 'react-native-barcode-mask';
import { useIsFocused, useNavigation } from '#react-navigation/native';
import CustomButton from '../components/CustomButton';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
export function ShowLoading(){
return(
<View style={styles.loader}><ActivityIndicator size="large" color='white'/></View>
)
}
export default function Scan(){
const navigation = useNavigation()
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [loading, setLoading] = useState(false);
const [type, setType] = useState(BarCodeScanner.Constants.Type.back);
const isFocused = useIsFocused()
useEffect(() => {
(async () => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
// useEffect(() => {
// if(loading){
// setLoading(true)
// } else {
// setLoading(false)
// }
// },[loading])
const initScanner = async() => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
}
const handleNavigation = async() => {
setScanned(false)
navigation.navigate('Oefening')
}
const handleNo = () => {
setScanned(false)
}
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true)
setLoading(true)
setTimeout(() => { Alert.alert(
'QR-Code gevonden',
`QR-Code met type ${type} en data ${data} is gescand, wilt u verder gaan?`,
[
{
text: "Nee",
onPress: () => handleNo(),
},
{
text: "Ja",
onPress: () => handleNavigation(),
}
]
), setLoading(false)}, 1000)
}
if (hasPermission === null) {
return <View style={styles.permissionWrapper}>
<Text style={styles.permissionText}>Een moment geduld..</Text>
<ActivityIndicator size='large' color='#1f69b1'></ActivityIndicator>
</View>;
}
if (hasPermission === false) {
return <Text>Geen toegang tot uw camera!</Text>;
}
return (
<View style={{flex: 1, flexDirection: 'column', justifyContent: 'flex-end'}}>
{loading? (<View style={styles.loader}><ActivityIndicator size='large' color='#1f69b1'></ActivityIndicator></View>
) : (
isFocused &&
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
type={type}
>
<View style={styles.topOptions}>
<View style={styles.cameraRotateWrapper}>
<Pressable style={styles.cameraRotate}
onPress={() => {
setType(
type === BarCodeScanner.Constants.Type.back
? BarCodeScanner.Constants.Type.front
: BarCodeScanner.Constants.Type.back
);
}}
>
<Icon name='rotate-3d-variant' size={40} color={'white'}></Icon>
</Pressable>
</View>
</View>
<BarcodeMask edgeColor={'#62B1F6'} showAnimatedLine={true}/>
</BarCodeScanner>)}
{scanned? <View style={styles.searchTextWrapper}><Text style={styles.searchText}>Gevonden!</Text></View> : <View style={styles.searchTextWrapper}><Text style={styles.searchText}>Zoeken naar QR-Code.... </Text></View>}
{/* {scanned? <Button title={'Opnieuw scannen'} onPress={() => setScanned(false)} /> : null} */}
<View style={styles.bottomOptions}>
<CustomButton textValue="Herladen" onPress={initScanner}></CustomButton>
</View>
</View>
)
}
const styles = StyleSheet.create({
loader: {
justifyContent: "center",
alignItems: 'center',
},
permissionWrapper: {
justifyContent: 'center',
alignItems:'center',
margin: 15,
},
permissionText: {
fontSize: 16,
fontWeight: 'bold',
},
topOptions: {
marginTop: 20,
justifyContent: 'space-between',
marginHorizontal: '10%'
},
searchTextWrapper: {
},
searchText: {
color: 'white',
fontSize: 18,
textAlign: 'center',
},
cameraRotateWrapper: {
width: 50,
height: 50,
},
cameraRotate: {
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
borderColor: "white",
backgroundColor: '#1f69b1',
borderRadius: 10,
},
bottomOptions: {
marginHorizontal: '10%',
marginBottom: 10,
},
})

How to useState hooks with array

I am not able to push the number index in the array of useState.
Where I am going wrong, do I want to push the index of numbers when I click them?
I am extracting the previous state array and then I push new but nothing happens.
How to push a new element inside useState array React hook? My code doesn't work!!
Please someone check.
Game.js
import { StatusBar } from "expo-status-bar";
import React, { useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import RandomNumber from "./RandomNumber";
export default function Game(props) {
const [state, setstate] = useState([]);
let randomNumber = Array.from({ length: props.randomNumberCount }).map(
() => 1 + Math.floor(10 * Math.random())
);
let target = randomNumber
.slice(0, props.randomNumberCount - 2)
.reduce((acc, curr) => acc + curr, 0);
const isNumberSelected = (numberIndex) => {
return state.indexOf(numberIndex) >= 0;
};
const selectNumber = (numberIndex) => {
setstate((arr) => [...arr, numberIndex]);
};
return (
<View style={styles.container}>
<Text style={styles.header}>Target Sum Game</Text>
<Text style={styles.target}>{target}</Text>
<View style={styles.randomContainer}>
{randomNumber.map((randomNumber, index) => (
<RandomNumber
key={index}
id={index}
number={randomNumber}
isSelected={isNumberSelected(index)}
onClick={() => selectNumber}
/>
))}
</View>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ddd",
paddingTop: 30,
},
target: {
fontSize: 30,
backgroundColor: "#aaa",
margin: 50,
marginHorizontal: 70,
textAlign: "center",
},
header: {
fontSize: 35,
backgroundColor: "dodgerblue",
textAlign: "center",
marginHorizontal: 30,
marginTop: 50,
},
randomContainer: {
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "space-around",
},
});
RandomNumber.js
import React from "react";
import { StyleSheet, Text, TouchableOpacity } from "react-native";
export default function RandomNumber(props) {
const handlePress = () => {
props.onClick(props.id);
};
return (
<TouchableOpacity onPress={handlePress()}>
<Text style={[styles.random, props.isSelected && styles.selected]}>
{props.number}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
random: {
backgroundColor: "#999",
width: 100,
marginHorizontal: 35,
marginVertical: 25,
fontSize: 35,
textAlign: "center",
},
selected: {
opacity: 0.3,
},
});
you are not calling the function
onClick={() => selectNumber(index)}
You need to change the onClick prop and pass the randomNumber (or index depending of what you want to do) to the selectNumber function:
// Not sure if you want to pass randonNumber or index but you get the idea
onClick={() => selectNumber(randomNumber)}
<TouchableOpacity onPress={handlePress()}>
should be
<TouchableOpacity onPress={()=>handlePress()}>
and
() => selectNumber
should be
() => selectNumber()
please try it
Might Be This Helpful:
Home.Js
import React, {useState, useEffect} from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import RandomNumber from './RandomNumber';
const Home = props => {
const [state, setstate] = useState([]);
useEffect(() => {
console.log('state', state);
}, [state]);
let randomNumber = Array.from({length: 10}).map(
() => 1 + Math.floor(10 * Math.random()),
);
let target = randomNumber
.slice(0, props.randomNumberCount - 2)
.reduce((acc, curr) => acc + curr, 0);
const isNumberSelected = numberIndex => {
return state.indexOf(numberIndex) >= 0;
};
const selectNumber = numberIndex => {
console.log('numberIndex', numberIndex);
setstate(arr => [...arr, numberIndex]);
};
return (
<View style={styles.container}>
<Text style={styles.header}>Target Sum Game</Text>
<Text style={styles.target}>{target}</Text>
<View style={styles.randomContainer}>
{randomNumber.map((randomNumber, index) => {
return (
<RandomNumber
key={index}
id={index}
number={randomNumber}
isSelected={isNumberSelected(index)}
onClick={() => selectNumber(randomNumber)}
/>
);
})}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ddd',
paddingTop: 30,
},
target: {
fontSize: 30,
backgroundColor: '#aaa',
margin: 50,
marginHorizontal: 70,
textAlign: 'center',
},
header: {
fontSize: 35,
backgroundColor: 'dodgerblue',
textAlign: 'center',
marginHorizontal: 30,
marginTop: 50,
},
randomContainer: {},
});
export default Home;
RandomNumber.js
import React from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
export default function RandomNumber(props) {
const handlePress = () => {
props.onClick(props.id);
};
return (
<View style={{}}>
<TouchableOpacity onPress={() => handlePress()}>
<Text style={[styles.random, props.isSelected && styles.selected]}>
{props.number}
</Text>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
random: {
backgroundColor: '#999',
width: 100,
height: 100,
marginHorizontal: 35,
marginVertical: 25,
fontSize: 35,
textAlign: 'center',
},
selected: {
opacity: 0.3,
},
});
Output Log:

Categories