View dont refresh when add a new json object in array. REACT NATIVE - javascript

the program compiles perfect, but when I scan a product, it doesn't refresh in the view.
I have mounted a mysql xampp with all the products. when querying a barcode. I get in response the detail of the product, and, add the json response with parse object in a array.
the view refresh when click TouchableOpacity, later of scan a product.
import React, {Component, useState, useEffect} from 'react';
import {Dimensions,Image, View, Text,AsyncStorage, TouchableOpacity, Grid, StyleSheet, ScrollView,ToastAndroid} from 'react-native';
import { SearchBar, Card, Icon } from 'react-native-elements';
import { BarCodeScanner } from 'expo-barcode-scanner';
//import { NumberList } from './NumberList';
const {width, height} = Dimensions.get('window');
const urlApi = "http://192.168.1.24/rst/api/getProduct.php";
const numbers = [1,2,3,4,5,6];
class SaleScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
scan: false,
result: null,
ScanResult: false,
hasPermission: true,
setHasPermission: true,
productos: [],
jwt: null,
};
//this.componentDidMount();
}
async componentDidMount(){
let _jwt = await AsyncStorage.getItem('userToken');
this.setState({
jwt: _jwt
});
}
_searchProduct = async (data) => {
try {
let response = await fetch(urlApi,{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer '+this.state.jwt
},
body: JSON.stringify({
CodiBarra: data
})
});
let responseJson = await response.json();
//console.log(responseJson);
if (responseJson.codibarra === null) {
//console.log("retorna falso");
return false;
}
else
{
if(this.state.productos != null)
{
this.state.productos.push(responseJson[0]);
//this.setState({productos: this.state.productos.push(responseJson[0])})
//console.log(this.state.productos);
}
else
{
this.state.productos.push(responseJson[0]);
}
}
} catch (error) {
console.error(error);
}
};
render(){
const { scan, ScanResult, result, hasPermission, setHasPermission, productos } = this.state;
const activeBarcode = ()=> {
this.setState({
scan: true
})
}
const handleBarCodeScanned = async ({ type, data }) => {
//console.log('scanned data' + data);
this.setState({result: data, scan: false, ScanResult: false});
this._searchProduct(data);
};
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}}>
{productos.length == 0 &&
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
}
{productos.length>0 &&
<View style={{flex:1}}>
<View style = {styles.button}>
<TouchableOpacity
onPress= {activeBarcode}
style={{
borderWidth:1,
borderColor:'rgba(0,0,0,0.2)',
alignItems:'center',
justifyContent:'center',
width:50,
height:50,
backgroundColor:'#fff',
borderRadius:50,
position: 'absolute',
marginTop: 10,
marginLeft: width - 100
}}
>
<Icon
type="font-awesome"
name="barcode"
/>
</TouchableOpacity>
</View>
<View style ={{flex:1,marginTop:20}}>
<ScrollView>
<NumberList products={this.state.productos} />
</ScrollView>
</View>
<View style ={{flex:1,marginTop:20}}>
<View style={{flexDirection:"row", height: 50, width: width, backgroundColor: "green", justifyContent: "center",}}>
<View style = {{ flexDirection:"column"}}>
<Text style = {{ fontSize: 40,color:"white"}}>{"TOTAL: "}</Text>
</View>
<View style={{justifyContent: "center", flexDirection:"row-reverse", paddingRight:20}}>
<Text style = {{ fontSize: 40,color:"white"}}>{result.precioventa}</Text>
</View>
</View>
</View>
</View>
}
{scan &&
<BarCodeScanner
onBarCodeScanned={handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
}
</View>
);
}
}
function NumberList(props) {
console.log("NUMBERLIST")
console.log(props);
const products = props.products;
const listItems = products.map((product) =>
// Correct! Key should be specified inside the array.
<ListItem key={product.key} value={product} />
);
return (
<View>
{listItems}
</View>
);
}
function ListItem(props) {
// Correct! There is no need to specify the key here:
const u = props.value;
return (
<View>
{u &&
<Card>
<View style={{flexDirection:"row"}}>
<Icon
name = "monetization-on"
size = {40}
/>
<View style={{flex:1, flexDirection: "column", paddingTop: 10}}><Text>{u.descripcion}</Text></View>
<View style = {{flexDirection:"row-reverse", paddingTop: 10}}><Text>{u.precioventa}</Text></View>
</View>
</Card>
}
</View>);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'black'
},
containerHome:{
backgroundColor: 'white',
height: height,
width: width,
flexDirection: 'column'
},
cardSales:{
backgroundColor: 'white',
flex: 1,
padding: 15,
borderWidth: 1,
borderRadius: 10,
borderColor: '#ddd',
borderBottomWidth: 7,
//shadowColor: '#000',
shadowColor: "#191919",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.8,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop: 20,
},
cardContent:{
flexDirection: 'row-reverse',
fontSize: 50
},
button:{
flexDirection: 'column',
marginTop: 20,
marginLeft: 20,
marginRight: 20,
},
contentActionFast:{
backgroundColor: 'white',
flexDirection: 'row',
alignItems:'center',
justifyContent: 'space-between',
flex:1
}
});
export default SaleScreen;
if anyone could help me I'd really appreciate it

Your component isn't re-rendering because in _searchProduct you're doing this.state.productos.push(responseJson[0]); to update the state object when you should be using setState(). Directly modifying the state, which you're doing now, won't trigger a re-render and could lead to other problems, which is why you should never do it and always use setState() (or a hook) to update state. This is mentioned in the docs here: https://reactjs.org/docs/state-and-lifecycle.html#do-not-modify-state-directly.
Instead try:
this.setState((prevState) => ({
productos: [...prevState.productos, responseJson[0]]
});

Related

Resulting in a blank screen when listing data with Firebase(Firestore) in React Native

Data listing process with Firebase(Firestore) in React Native.
In the video I watched, he wrote and ran the code that lists the coins belonging to the user using firestore. It did not work even though I wrote the same codes. What is the reason? the code does not give an error, the screen appears, but it does not list.
The problem is that when I did the listing in console it worked. However, when I try to list with FlatList, the screen appears blank.
import { View, Text, SafeAreaView, TouchableOpacity, FlatList } from 'react-native'
import React, { useContext, useState, useEffect } from 'react'
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
import IconFA from 'react-native-vector-icons/FontAwesome'
import { deviceWidth, deviceHeight } from '../../utils/dimensions'
import { AuthContext } from '../../navigation/AuthProvider'
import { Formik, validateYupSchema } from 'formik'
import * as yup from 'yup'
import { firebase } from '#react-native-firebase/auth'
import auth from '#react-native-firebase/auth'
import firestore from '#react-native-firebase/firestore'
const color = '#aaa';
const HomeScreen = ({ navigation }) => {
const renderItem = (item) => {
<TouchableOpacity
key={item.id}
style={{
flexDirection: 'row',
width: '95%',
height: 60,
borderWidth: 1,
margin: 10,
borderRadius: 20,
padding: 10,
justifyContent: 'space-between',
alignItems: 'center'
}}>
<View style={{ flex: 1 }}>
<Text style={{
textAlign: 'left',
fontSize: 18
}}>{item.coinID}</Text>
</View>
<View style={{ flex: 1 }}>
<Text style={{
textAlign: 'right',
fontSize: 18
}}>{item.value}</Text>
</View>
</TouchableOpacity>
}
const { signOut, user } = useContext(AuthContext);
const [currentUser, setCurrentUser] = useState({});
const [userCoinList, setUserCoinList] = useState([]);
const usersColl = firestore().collection('users');
const coinsColl = firestore().collection('coins');
const userCoinsColl = firestore().collection('userCoins');
useEffect(() => {
return usersColl
.doc(user.uid)
.get()
.then(result => {
setCurrentUser(result.data());
userCoinsColl.onSnapshot((querySnapshot) => {
let list = [];
querySnapshot.forEach(doc => {
const { userID, coinID, value } = doc.data();
if (userID == user.uid) {
list.push({
id: doc.id,
userID,
coinID,
value
});
setUserCoinList(list);
}
});
});
});
}, []);
return (
<SafeAreaView style={{ width: '100%', height: '100%' }}>
<View style={{
width: '100%',
height: '90%',
padding: 5,
flex: 1,
alignItems: 'center'
}}>
<View>
<FlatList
style={{ flex: 3, backgroundColor: '#f00' }}
data={userCoinList}
keyExtractor={item => item.id}
renderItem={renderItem}
/>
{console.log(userCoinList)}
</View>
</View>
</SafeAreaView>
)
}
export default HomeScreen
Your renderItem function does not return anything.
Here is a fix.
const renderItem = (item) => {
return <TouchableOpacity
key={item.id}
style={{
flexDirection: 'row',
width: '95%',
height: 60,
borderWidth: 1,
margin: 10,
borderRadius: 20,
padding: 10,
justifyContent: 'space-between',
alignItems: 'center'
}}>
<View style={{ flex: 1 }}>
<Text style={{
textAlign: 'left',
fontSize: 18
}}>{item.coinID}</Text>
</View>
<View style={{ flex: 1 }}>
<Text style={{
textAlign: 'right',
fontSize: 18
}}>{item.value}</Text>
</View>
</TouchableOpacity>
}

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)
}
*/

How to Pass Props to Modal Component in React Native

I need to pass Flatlist data to modal in react native. Like, on click the item from the flatlist, it shows the modal with data for selected item. Here is my code below
Home.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, FlatList, Image, TouchableOpacity, Alert, Button } from 'react-native';
import { Popup } from './Modal';
import * as productdata from '../data/productdata.js';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
this.setState({
isLoading: false,
dataSource: productdata.product,
})
}
popupRef = React.createRef()
onShowPopup = item => {
popupRef.show();
}
onClosePopup = () => {
popupRef.close()
}
ProductList = ({ item }) => (
<View style={styles.listItem}>
<TouchableOpacity onPress={() => this.onShowPopup(item)} style={{ height: 100, width: 100, justifyContent: "center", alignItems: "center" }}>
<Image source={item.photo} style={{ width: 100, height: 100, borderRadius: 15 }} />
</TouchableOpacity>
<View style={{ alignItems: "center", flex: 1, marginTop: 20 }}>
<Text style={{ fontWeight: "bold", fontSize: 22 }}>{item.name}</Text>
<Text style={{ fontSize: 18, fontWeight: "bold" }}>{item.price}</Text>
</View>
<Popup name="Product Details" ref={(target) => popupRef = target} onTouchOutside={this.onClosePopup} />
</View>
);
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={this.ProductList}
keyExtractor={item => item.name}
/>
</View>
);
}
}
Modal.js
import React, { Component } from 'react';
import { Modal, Dimensions, TouchableWithoutFeedback, StyleSheet, View, Text, Button, Image, TouchableOpacity } from 'react-native';
const deviceHeight = Dimensions.get("window").height
export class Popup extends Component {
constructor(props) {
super(props)
this.state = {
show: false,
}
}
show = () => {
this.setState({ show: true })
}
close = () => {
this.setState({ show: false })
}
renderOutsideTouchable(onTouch) {
const view = <View style={{ flex: 1, width: '100%' }} />
if (!onTouch) return view
return (
<TouchableWithoutFeedback onPress={onTouch} style={{ flex: 1, width: '100%' }}>
{view}
</TouchableWithoutFeedback>
)
}
renderTitle = () => {
const { name } = this.props
return (
<View style={{ alignItems: 'center' }}>
<Text style={{
color: 'black', fontSize: 20,
fontWeight: 'bold', margin: 15
}}>
{name}
</Text>
</View>
)
}
renderContent = (item) => {
return (
<View style={{ alignItems: 'center', marginBottom: 10 }}>
<View style={styles.card}>
<Text style={{ fontSize: 20, fontWeight: '500', fontWeight: 'bold', alignSelf: 'center', margin: 5 }}/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.button}>Add to Cart</Text>
</TouchableOpacity>
</View>
</View>
)
}
render() {
let { show } = this.state
const { onTouchOutside, title } = this.props
return (
<Modal animationType={'slide'} transparent={true} visible={show} onRequestClose={this.close}>
<View style={{ flex: 1, backgroundColor: '#000000AA', justifyContent: 'flex-end' }}>
{this.renderOutsideTouchable(onTouchOutside)}
<View style={{
backgroundColor: '#FFFFFF', width: '100%', height: '70%', borderTopRightRadius:20, borderTopLeftRadius: 20, paddingHorizontal: 20, maxHeight: deviceHeight * 5}}>
{this.renderTitle()}
{this.renderContent()}
</View>
</View>
</Modal>
)
}
}
My Problem: I am not able to pass the flatlist item data to a Modal component and have no better idea solving it in this code.
Please help me and if any including, changes or complete solution for perfect understanding for the requirement would be really great. Many Thanks in Advance!
You don't need to duplicate open state in modal/popup. Simply set the style and open. Assume open close state is controlled by parent component, so if rendering modal/popup it is open by definition.
class Popup extends React.Component {
renderOutsideTouchable(onTouch) {
const view = <View style={{ flex: 1, width: '100%' }} />;
if (!onTouch) return view;
return (
<TouchableWithoutFeedback
onPress={onTouch}
style={{ flex: 1, width: '100%' }}>
{view}
</TouchableWithoutFeedback>
);
}
renderTitle = () => {
const { name } = this.props;
return (
<View style={{ alignItems: 'center' }}>
<Text
style={{
color: 'black',
fontSize: 20,
fontWeight: 'bold',
margin: 15,
}}>
{name}
</Text>
</View>
);
};
renderContent = () => {
const { item } = this.props;
return (
<View style={{ alignItems: 'center', marginBottom: 10 }}>
<View style={styles.card}>
<Text
style={{
fontSize: 20,
fontWeight: '500',
// fontWeight: "bold",
alignSelf: 'center',
margin: 5,
}}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text>Name: {item.name}</Text>
<Text>Price: {item.price}</Text>
<Text>Description: {item.desc}</Text>
<Text>Rating: {item.rating}</Text>
<Text style={styles.button}>Add to Cart</Text>
</TouchableOpacity>
</View>
</View>
);
};
render() {
const { onTouchOutside, title } = this.props;
return (
<Modal
animationType={'slide'}
transparent
visible // <-- visible prop is truthy
onRequestClose={this.close}>
<View
style={{
flex: 1,
backgroundColor: '#000000AA',
justifyContent: 'flex-end',
zIndex: 1000,
}}>
{this.renderOutsideTouchable(onTouchOutside)}
<View
style={{
backgroundColor: '#FFFFFF',
width: '100%',
height: '70%',
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingHorizontal: 20,
maxHeight: deviceHeight * 5,
}}>
{this.renderTitle()}
{this.renderContent()}
</View>
</View>
</Modal>
);
}
}
A react ref isn't necessary for opening a modal/popup to display a specific item. Change the onShowPopup and onClosePopup to set/nullify a clicked on item. Conditionally render the Popup outside the Flatlist.
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
dataSource: productdata.product,
isLoading: false,
popupItem: null,
};
}
onShowPopup = (popupItem) => {
this.setState({ popupItem });
};
onClosePopup = () => {
this.setState({ popupItem: null });
};
ProductList = ({ item }) => (
<View style={styles.listItem}>
<TouchableOpacity
onPress={() => this.onShowPopup(item)}
style={{
height: 100,
width: 100,
justifyContent: 'center',
alignItems: 'center',
}}>
<Image
source={item.photo}
style={{ width: 100, height: 100, borderRadius: 15 }}
/>
</TouchableOpacity>
<View style={{ alignItems: 'center', flex: 1, marginTop: 20 }}>
<Text style={{ fontWeight: 'bold', fontSize: 22 }}>{item.name}</Text>
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>{item.price}</Text>
</View>
</View>
);
render() {
return (
<View style={styles.container}>
{this.state.popupItem && (
<Popup
name="Product Details"
item={this.state.popupItem} // <-- pass pop item
onTouchOutside={this.onClosePopup}
/>
)}
<FlatList
data={this.state.dataSource}
renderItem={this.ProductList}
keyExtractor={(item) => item.name}
/>
</View>
);
}
}
Expo Snack

TypeError: undefined is not an object (evaluating 'this.state.googleResponse.responses[0]')

I am totally new at this, and I am using Google Vision with my React Native app on Expo to label documents. I based it off this project:
https://github.com/crowdbotics-apps/rngooglevisionapi-1400/blob/master/frontend/App.js
And I edited it to use Document Text Detection instead.
However, this error keeps coming up.
The only place I am using this.state.googleResponse.responses[0] in my code is:
render() {
let { image } = this.state;
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.getStartedContainer}>
{image ? null : (
<Text style={styles.getStartedText}>Smart Text Extractor</Text>
)}
</View>
<View style={styles.helpContainer}>
<View style={{ margin: 20 }}>
<Button
onPress={this._pickImage}
title="Pick an image from Gallery"
color="#3b5998"
/>
</View>
<Button
onPress={this._takePhoto}
title="Take a photo"
color="#1985bc"
/>
{this.state.googleResponse && (
<FlatList
data={this.state.googleResponse.responses[0].fullTextAnnotation}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.description}
</Text>
)}
/>
)}
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
</View>
</ScrollView>
</View>
);
My entire code is
import React, { Component } from 'react';
import {
View,
Image,
Text,
StyleSheet,
ScrollView,
ActivityIndicator,
Button,
FlatList,
Clipboard
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import * as Permissions from 'expo-permissions';
import uuid from 'uuid';
import Environment from './src/config/environment';
import firebase from './src/config/firebase';
//console.disableYellowBox = true;
async function uploadImageAsync(uri) {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child(uuid.v4());
const snapshot = await ref.put(blob);
blob.close();
return await snapshot.ref.getDownloadURL();
}
export default class App extends Component {
state = {
image: null,
uploading: false,
googleResponse: null
};
async componentDidMount() {
await Permissions.askAsync(Permissions.CAMERA_ROLL);
await Permissions.askAsync(Permissions.CAMERA);
}
organize = array => {
return array.map(function(item, i) {
return (
<View key={i}>
<Text>{item}</Text>
</View>
);
});
};
_maybeRenderUploadingOverlay = () => {
if (this.state.uploading) {
return (
<View
style={[
StyleSheet.absoluteFill,
{
backgroundColor: 'rgba(255,255,255,0.4)',
alignItems: 'center',
justifyContent: 'center'
}
]}
>
<ActivityIndicator color="#fff" animating size="large" />
</View>
);
}
};
_maybeRenderImage = () => {
let { image, googleResponse } = this.state;
if (!image) {
return;
}
return (
<View
style={{
marginTop: 20,
width: 250,
borderRadius: 3,
elevation: 2
}}
>
<Button
style={{ marginBottom: 10 }}
onPress={() => this.submitToGoogle()}
title="Analyze!"
/>
<View
style={{
borderTopRightRadius: 3,
borderTopLeftRadius: 3,
shadowColor: 'rgba(0,0,0,1)',
shadowOpacity: 0.2,
shadowOffset: { width: 4, height: 4 },
shadowRadius: 5,
overflow: 'hidden'
}}
>
<Image source={{ uri: image }} style={{ width: 250, height: 250 }} />
</View>
<Text
onPress={this._copyToClipboard}
onLongPress={this._share}
style={{ paddingVertical: 10, paddingHorizontal: 10 }}
/>
<Text>Raw JSON:</Text>
{googleResponse && (
<Text
onPress={this._copyToClipboard}
onLongPress={this._share}
style={{ paddingVertical: 10, paddingHorizontal: 10 }}
>
{JSON.stringify(googleResponse.responses)}
</Text>
)}
</View>
);
};
_keyExtractor = (item, index) => item.description;
_renderItem = item => {
<Text>response: {JSON.stringify(item)}</Text>;
};
_share = () => {
Share.share({
message: JSON.stringify(this.state.googleResponse.responses),
title: 'Check it out',
url: this.state.image
});
};
_copyToClipboard = () => {
Clipboard.setString(this.state.image);
alert('Copied to clipboard');
};
_takePhoto = async () => {
let pickerResult = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [4, 3]
});
this._handleImagePicked(pickerResult);
};
_pickImage = async () => {
let pickerResult = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
aspect: [4, 3]
});
this._handleImagePicked(pickerResult);
};
_handleImagePicked = async pickerResult => {
try {
this.setState({ uploading: true });
if (!pickerResult.cancelled) {
uploadUrl = await uploadImageAsync(pickerResult.uri);
this.setState({ image: uploadUrl });
}
} catch (e) {
console.log(e);
alert('Upload failed, sorry :(');
} finally {
this.setState({ uploading: false });
}
};
submitToGoogle = async () => {
try {
this.setState({ uploading: true });
let { image } = this.state;
let body = JSON.stringify({
requests: [
{
features: [
//{ type: 'TEXT_DETECTION'}, //maxResults: 5 },
{ type: 'DOCUMENT_TEXT_DETECTION'}//, maxResults: 5 }
],
image: {
source: {
imageUri: image
}
}
}
]
});
let response = await fetch(
'https://vision.googleapis.com/v1/images:annotate?key=' +
Environment['GOOGLE_CLOUD_VISION_API_KEY'],
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
method: 'POST',
body: body
}
);
let responseJson = await response.json();
console.log(responseJson);
this.setState({
googleResponse: responseJson,
uploading: false
});
} catch (error) {
console.log(error);
}
};
render() {
let { image } = this.state;
console.log(this.state.googleResponse)
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={styles.getStartedContainer}>
{image ? null : (
<Text style={styles.getStartedText}>Smart Text Extractor</Text>
)}
</View>
<View style={styles.helpContainer}>
<View style={{ margin: 20 }}>
<Button
onPress={this._pickImage}
title="Pick an image from Gallery"
color="#3b5998"
/>
</View>
<Button
onPress={this._takePhoto}
title="Take a photo"
color="#1985bc"
/>
{this.state.googleResponse && (
<FlatList
data={this.state.googleResponse.responses[0].fullTextAnnotation}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.description}
</Text>
)}
/>
)}
{this._maybeRenderImage()}
{this._maybeRenderUploadingOverlay()}
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ebebeb',
paddingBottom: 10
},
developmentModeText: {
marginBottom: 20,
color: 'rgba(0,0,0,0.4)',
fontSize: 14,
lineHeight: 19,
textAlign: 'center'
},
contentContainer: {
paddingTop: 30
},
getStartedContainer: {
alignItems: 'center',
marginHorizontal: 50,
marginVertical: 50
},
getStartedText: {
fontSize: 24,
color: '#000',
fontWeight: 'bold',
textAlign: 'center'
},
helpContainer: {
marginTop: 15,
alignItems: 'center'
},
textText: {
fontSize: 20,
fontWeight: '600'
}
});
//export default App;
Any ideas please?
I think google vision response contain text and bounding. Please update the FlatList component.
<FlatList
data={this.state.googleResponse}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={({ item }) => (
<Text style={styles.textText}>
Text Detected: {item.text}
</Text>
)}
/>
Note: Make sure the this.state.googleResponse must be response of vision api. You can check it by using console.log(this.state.googleResponse) in render method.

Adding background image to create-react-native project

I am trying to insert a background image into my create-react-native project. I would like to be able to add this image: https://i.pinimg.com/736x/80/29/a9/8029a9bf324c79b4803e1e5a2aba25f3--costume-makeup-iphone-wallpaper.jpg. I have tried applying it to the stylesheet but it is not accepting the background-image tag. I am very new at react.
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button} from 'react-native';
import ListItem from "/Users/Westin/assignment5/ListItem";
export default class App extends React.Component {
state ={
thing: "",
things: [],
};
thingValueChanged = value =>{
//alert(value);
this.setState({
thing: value
});
}
onClickingAdd = () =>
{
if(this.state.thing === "")
{
return;
}
this.setState(prevState => {
return {
things: prevState.things.concat(prevState.thing)
};
});
}
render() {
const thingsOut = this.state.things.map((thing,i) => (<ListItem key = {i} thing={thing} />))
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}>My Favourite Things</Text>
</View>
<View style={styles.input}>
<TextInput
value={this.state.thing}
placeholder="Add your favourite things"
style={styles.inputbox}
onChangeText={this.thingValueChanged}
/>
<Button
title="Add"
style={styles.addButton}
onPress = {this.onClickingAdd}
/>
</View>
<View>
{thingsOut}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e6eeff',
alignItems: 'center',
justifyContent: 'flex-start',
paddingTop: 30,
},
header: {
padding: 10,
},
headerText: {
fontSize: 30,
color: '#003cb3',
},
inputbox: {
borderWidth: 1,
height: 40,
width: "70%",
},
addButton: {
width: "30%"
},
input: {
flexDirection: "row",
width: '100%',
justifyContent: "space-evenly",
alignItems: "center",
}
});
This is the code I tried to run
import React from 'react';
import { StyleSheet, Text, View, TextInput, Button, Image } from 'react-native';
import ListItem from "/Users/Westin/assignment5/ListItem";
const remote = 'https://i.pinimg.com/736x/80/29/a9/8029a9bf324c79b4803e1e5a2aba25f3--costume-makeup-iphone-wallpaper.jpg';
export default class BackgroundImage extends Component {
render() {
const resizeMode = 'center';
return (
<Image
style={{
flex: 1,
resizeMode,
}}
source={{ uri: remote }}
/>
);
}
}
AppRegistry.registerComponent('BackgroundImage', () => BackgroundImage);
export default class App extends React.Component {
state ={
thing: "",
things: [],
};
thingValueChanged = value =>{
//alert(value);
this.setState({
thing: value
});
}
onClickingAdd = () =>
{
if(this.state.thing === "")
{
return;
}
this.setState(prevState => {
return {
things: prevState.things.concat(prevState.thing)
};
});
}
render() {
const thingsOut = this.state.things.map((thing,i) => (<ListItem key = {i} thing={thing} />))
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.headerText}>My Favourite Things</Text>
</View>
<View style={styles.input}>
<TextInput
value={this.state.thing}
placeholder="Add your favourite things"
style={styles.inputbox}
onChangeText={this.thingValueChanged}
/>
<Button
title="Add"
style={styles.addButton}
onPress = {this.onClickingAdd}
/>
</View>
<View>
{thingsOut}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
backgroundColor: 'black',
opacity: 0.5,
justifyContent: 'flex-start',
paddingTop: 30,
},
header: {
padding: 10,
},
headerText: {
fontSize: 30,
color: '#003cb3',
},
inputbox: {
borderWidth: 1,
height: 40,
width: "70%",
backgroundColor: 'white',
},
addButton: {
width: "30%"
},
input: {
flexDirection: "row",
width: '100%',
justifyContent: "space-evenly",
alignItems: "center",
}
});
It said I cant run two export classes
This code works for me:
import React from 'react';
import { StyleSheet, Text, View, ImageBackground } from 'react-native';
export default class App extends React.Component {
render() {
return (
<ImageBackground source=
{ {uri: 'https://i.pinimg.com/736x/80/29/a9/8029a9bf324c79b4803e1e5a2aba25f3--costume-makeup-iphone-wallpaper.jpg' } }
style={styles.container}
>
<Text>Some</Text>
<Text>Text</Text>
<Text>Centered</Text>
<Text>In</Text>
<Text>Columns</Text>
</ImageBackground>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
width: '100%'
},
});
You can read more about <ImageBackground/> here: https://facebook.github.io/react-native/docs/images#background-image-via-nesting

Categories

Resources