user889030
user889030

Reputation: 4754

React Native how to update UI from another function

I am new to react and am trying to create a basic bar code scanner using this example: https://docs.expo.io/versions/latest/sdk/bar-code-scanner/

import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button , ViewPropTypes , SafeAreaView, ScrollView} from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';

export default function App() {
    return ( 
    <View>      
     <ScrollView style={styles.scrollView}>
        <Text style={styles.text}>{"bar code reading goes here"}</Text>
    </ScrollView>   
    {BarCoderScanner()}
    </View> 
         
    );
    
}

function bscanner(){

  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);
    return(
     <ScrollView style={styles.scrollView}>
        <Text style={styles.text}>${data}</Text>
    </ScrollView>
    );
  };

  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>

  );
}

I am wondering how I can update the main UI, aka App(), from the callback function handleBarCodeScanned.

Upvotes: 1

Views: 1078

Answers (2)

Arif Arifi
Arif Arifi

Reputation: 1502

Try this:

import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, Button , ViewPropTypes , SafeAreaView, ScrollView} from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';

export default function App() {
    const [data, setData] = useState('');
   
    return ( 
    <View>      
     <ScrollView style={styles.scrollView}>
        <Text style={styles.text}>{data}</Text>
    </ScrollView>   
    <BScanner onRead={item => setData(item)} />
    </View> 
         
    );
    
}

function BScanner({onRead}){

  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);
    onRead(data);
  };

  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>

  );
}

Upvotes: 2

Null
Null

Reputation: 518

  1. Create a new state variable: const [data, setData] = useState("");
  2. After you call setScanned(true); call setData(data)
  3. Remove the return code from handleBarCodeScanned
  4. Change this line {scanned && <Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />} to {scanned ? (<ScrollView style={styles.scrollView}><Text style={styles.text}>{data}</Text></ScrollView>) : (<Button title={'Tap to Scan Again'} onPress={() => setScanned(false)} />)}
  • You can create a separate component for the scrollview to cleanup the code in the ternary.

Upvotes: 2

Related Questions