Well what I'm trying to do is when he finishes reading the qr code is to move to the next screen as soon as this event ends. I tried to do this by declaring:
const handleBarCodeScanned = ({ type, data }) => {
{this.props.navigation.navigate ('testScreen', {data1, data2})}
}
Usually, the documentation always shows accompanied by an onClick () function associated with a button.
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button, PermissionsAndroid } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
import wifi from 'react-native-android-wifi';
export default function QrCodeScreen() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
{this.props.navigation.navigate('nextScreen', { data1, data2 })}//Change screen
})}
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
}}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
{scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
</View>
);
}
Seems like you're using functional components so there is no this context.
You forget to import and init the navigation hook
import { useNavigation } from '#react-navigation/native';
And
export default function QrCodeScreen() {
const navigation = useNavigation();
...
Then
const handleBarCodeScanned = ({ type, data }) => {
navigation.navigate('nextScreen', { data1, data2 })
})}
I managed to solve the error by passing as the navigation parameter in the function declaration.
Before
export default function QrCodeScreen() {
}
After
export default function QrCodeScreen({navigation}) {
}
Change screen
navigation.navigate('SetupConnectionScreen');
Related
I have installed the expo camera tool with npm.
I run this code and it works on Snack :
import React, { useState, useEffect } from "react";
import { Text, View, StyleSheet, Button } from "react-native";
import { BarCodeScanner } from "expo-barcode-scanner";
import { Camera } from "expo-camera";
export default function Scanner() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<Camera
style={StyleSheet.absoluteFillObject}
onBarCodeScanned={console.log}
barCodeScannerSettings={{
barCodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
}}
/>
{scanned && (
<Button title={"Tap to Scan Again"} onPress={() => setScanned(false)} />
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
},
});
But in localhost I have the message "no access to camera"and I have no popup asking for access.
I am a complete beginner with react native and I can't figure out how to fix this ^^.
EDIT : I'm running it on web
I try to use the barcode-scanner on my react native app, but a I get this error :
Invalid hook call. Hooks can only be called inside of the body of a function component.
That is the code source of my component :
import React, { useState, useEffect, Component } from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
class QrCode extends Component {
render () {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={styles.container}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
{scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
});
export default QrCode;
I'm trying to build a Barcode scanner component and I'm using expo-barcode-scanner.
the console.log works fine and I get the ASKING text.
the dialog window doesnt show up
here is my code:
import React, { useState, useEffect } from 'react';
import { Text,SafeAreaView, View, StyleSheet, Button } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
const ScannerComponent =()=> {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const askForCameraPermission = () =>{
console.log('ASKING')
async () => {
const {status} = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
}
}
useEffect(() => {
askForCameraPermission();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
if (hasPermission === null) {
return (<View style={styles.container}><Text style={styles.text}>Requesting for camera permission</Text></View>);
}
if (hasPermission === false) {
return (<View style={styles.container}><Text style={styles.text}>No access to camera</Text></View>);
}
return (
<SafeAreaView style={styles.container}>
<Text value='hello' />
<View style={styles.scanner}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
</View>
{scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
</SafeAreaView>
);
}
export default ScannerComponent
Tech stack: Expo, React-Native
Using: expo-barcode-scanner
I am trying to create an app that will scan a QR code and then display the info from the QR code on the screen, preferably in a modal so I can display an image.
I've created an app that will do that... except that it uses an alert function to show the text. How can I change it to a modal? When I try to change it to modal, or return a modal it doesn't work.
My code:
import React, { useCallback, useEffect, useState } from 'react';
import { StyleSheet, Text, View, Image, Button, Modal } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
import {createCustomerInformation2} from './src/graphql/mutations'
import logo from './assets/icon.png';
import Scanner from './components/QRScanner';
import custModal from './components/custInfo'
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
// const [modalVisible, setModalVisible] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
var newData = JSON.parse(data)
// return(
// <View>
// <Modal>
// <View>
// <Text>Test</Text>
// </View>
// </Modal>
// </View>
// )
alert(`
Customer: ${newData.name}
Email: ${newData.email}
Phone: ${newData.phone}
Favorite Drink: ${newData.favoriteDrink}
`);
// createCustomerInformation2(newData)();
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View id="view" style={styles.container}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
// If you want to use the front facing or rear facing, include type={'front'} or put 'back'
/>
{scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
},
});
Instead of returning that JSX in the onBarCodeScanned handler, you'll need to include it in the returned JSX of your App. You'll want to conditionally hide the modal when no value is present. You'll then populate it by assigning the scanned value to a state variable in the event handler and displaying that value in the modal.
I'm tying to store the theme state in the app, so that the chosen theme will be persistent after the app is closed. I have two files, one is the App.js file which has the navigation, and the other is the DrawerContent.js file that has the content of the drawer as well as the switch for the theme. toggleTheme is passed to the DrawerContent through useContext.
These are the snippets of the App file.
import {
NavigationContainer,
DefaultTheme as NavigationDefaultTheme,
DarkTheme as NavigationDarkTheme
} from '#react-navigation/native';
import {
Provider as PaperProvider,
DefaultTheme as PaperDefaultTheme,
DarkTheme as PaperDarkTheme
} from 'react-native-paper';
import AsyncStorage from '#react-native-community/async-storage';
const THEME_KEY = 'theme_color';
export default function App() {
const [isDarkTheme, setIsDarkTheme] = useState(false);
{/* Themes */ }
const CustomDefaultTheme = {
...NavigationDefaultTheme,
...PaperDefaultTheme,
colors: {
...NavigationDefaultTheme.colors,
...PaperDefaultTheme.colors,
background: '#ffffff',
text: '#333333',
tab: '#0789DC'
}
}
const CustomDarkTheme = {
...NavigationDarkTheme,
...PaperDarkTheme,
colors: {
...NavigationDarkTheme.colors,
...PaperDarkTheme.colors,
background: '#333333',
text: '#ffffff',
tab: '#2c3e50'
}
}
const theme = isDarkTheme ? CustomDarkTheme : CustomDefaultTheme;
// AsyncSotrage
const storeTheme = async (key, isDarkTheme) => {
try {
await AsyncStorage.setItem(THEME_KEY, JSON.stringify(isDarkTheme))
setIsDarkTheme(isDarkTheme);
console.log(isDarkTheme)
} catch (error) {
alert(error);
}
}
const getTheme = async () => {
try {
const savedTheme = await AsyncStorage.getItem(THEME_KEY)
if (savedTheme !== null) {
setIsDarkTheme(JSON.parse(savedTheme));
}
} catch (error) {
alert(error);
}
}
const authContext = useMemo(() => ({
toggleTheme: () => {
setIsDarkTheme(isDarkTheme => !isDarkTheme);
// storeTheme(isDarkTheme => !isDarkTheme);
console.log(isDarkTheme);
}
}),
[]
);
useEffect(() => {
getTheme();
// Fetch the token from storage then navigate to our appropriate place
const bootstrapAsync = async () => {
let userToken;
try {
userToken = await AsyncStorage.getItem(USER_TOKEN)
if (userToken !== null) {
setUserToken(JSON.parse(userToken))
}
} catch (e) {
alert(e)
}
// After restoring token, we may need to validate it in production apps
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away.
dispatch({ type: 'RESTORE_TOKEN', token: userToken });
};
bootstrapAsync();
}, []);
return (
<PaperProvider theme={theme}>
<AuthContext.Provider value={authContext}>
<NavigationContainer theme={theme}>
...
</NavigationContainer>
</AuthContext.Provider>
</PaperProvider>
)
}
This is the DrawerContent code.
import {
useTheme,
Avatar,
Title,
Caption,
Paragraph,
Drawer,
Text,
TouchableRipple,
Switch
} from 'react-native-paper';
export function DrawerContent(props) {
const paperTheme = useTheme();
const { signOut, toggleTheme } = React.useContext(AuthContext);
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView>
<View style={styles.drawerContent}>
...
<Drawer.Section title="Preferences">
<TouchableRipple onPress={() => { toggleTheme() }}>
<View style={styles.preference}>
<Text>Dark Theme</Text>
<View pointerEvents="none">
<Switch
value={paperTheme.dark}
/>
</View>
</View>
</TouchableRipple>
</Drawer.Section>
</View>
</DrawerContentScrollView>
</View>
)
}
Perhaps the effective synchronous access of AsyncStorage can solve your problem. It is recommended that you use the react-native-easy-app open source library react-native-easy-app, through which you can access any data in AsyncStorage like memory objects.
For specific usage, maybe you can refer to the StorageController file in Project Sample_Hook