the following code works fine on iOS, but on android after loading the orders array and rendering it, the onpress event stops working, at first I thought it was a problem with firebase but then I did it locally and I get the same issue.
import React from 'react';
import {
ActivityIndicator,
Alert,
Button,
Dimensions,
Image,
StatusBar,
StyleSheet,
ScrollView,
Text,
TouchableOpacity,
View,
Platform,
RefreshControl,
YellowBox } from 'react-native';
import { Ionicons as Icon } from '#expo/vector-icons';
import { Card, DefaultTheme } from 'react-native-paper';
import NavigationService from '../../Navigation/navigationService';
import _ from 'lodash';
YellowBox.ignoreWarnings(['Setting a timer']);
const _console = _.clone(console);
console.warn = message => {
if (message.indexOf('Setting a timer') <= -1) {
_console.warn(message);
}
};
import Firebase from '../../connection/to-firebase';
const LOGO_URL = 'https://i.imgur.com/BbYaucd.png';
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
const styles = StyleSheet.create({
container: {
paddingTop: StatusBar.currentHeight,
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT / 2,
backgroundColor: "#317AFA",
},
innerContainer: {width:SCREEN_WIDTH, alignItems: 'center', justifyContent: 'center' },
header: {position:'absolute', padding: 15, paddingTop: Platform.OS === 'ios' ? 13 : 7, marginTop:SCREEN_HEIGHT*0.05,zIndex:99 },
scrollView: {
position:'absolute',
top:SCREEN_HEIGHT*0.35,
marginHorizontal: 20,
width: SCREEN_WIDTH*0.90,
height: SCREEN_HEIGHT,
zIndex:9999
},
textHeader:{
marginTop:10,
color: 'white',
fontWeight: 'bold',
fontSize: 40,
}
});
const theme = {
colors: {
...DefaultTheme.colors,
primary: '#3498db',
accent: '#f1c40f',
}
}
export default class DefaultScreen extends React.Component {
constructor (props) {
super(props)
console.ignoredYellowBox = [
'Setting a timer'
];
this.state = {
orders: [],
refreshing: false,
timePassed: false
}
}
_onRefresh = () => {
this.setState({refreshing: true});
this.getOrders().then(() => {
this.setState({refreshing: false});
});
//setTimeout(()=>{this.setState({refreshing: false})},1000)
}
async getOrders(){
//let result = await Firebase.extractOrder();
let result = [
{
"Note": "",
"coords": {
"finalLatitude": 14.100751767597542,
"finalLongitude": -87.18541710839844,
"initialLatitude": 14.061113522979957,
"initialLongitude": -87.21807641015624
},
"createdAt": {
"nanoseconds": 686000000,
"seconds": 1576188983
},
"destinataryName": "Eliana Martínez",
"destinataryPhone": "97412032",
"idSubcategory": "1",
"idUsuario": 1,
"isTakenBySomeone": false,
"orderID": "rQAt5IEI687AkoI8rShh",
"products": [
{
"id": 93634,
"observation": "",
"price": "56.00",
"quantity": 1
},
{
"id": 29909,
"observation": "",
"price": "131.00",
"quantity": 97
}
],
"status": "Pending",
"telephone": 23456987,
"transportType": "Motocicleta"
}
]
this.setState({ orders: result});
}
componentDidMount(){
//this.getOrders();
}
renderOrders = (orders) =>{
return orders.map((a,b)=>{
return [
<MainOrders key={a.orderID} dName= {a.orderID} note ={a.Note} transType={a.transportType} orderDetails={a}
navigation={this.props.navigation}
/>
]
})
}
render() {
setTimeout(()=>{this.setState({timePassed: true})}, 1000);
if (!this.state.timePassed){
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<View style={styles.header}>
<TouchableOpacity
onPress={() => {
this.props.navigation.openDrawer();
}}
style = {{marginTop:'10%'}}
>
<Icon name="md-menu" size={35} color={'#fff'}/>
</TouchableOpacity>
<Text style={styles.textHeader}>Home</Text>
</View>
<View style={styles.innerContainer}>
<ScrollView style={styles.scrollView}
refreshControl={ <RefreshControl refreshing={this.state.refreshing} onRefresh={this._onRefresh}/>}
>
<Card theme={theme}>
<Card.Title title="Order List" subtitle="" />
<Card.Content>
<ActivityIndicator size="small" color="#317AFA" />
</Card.Content>
<Card.Actions>
<Button title="View Order" style={{zIndex:9999, elevation:15}} onPress={()=>{
Alert.alert('Hello World')
}}>View Order</Button>
</Card.Actions>
</Card>
</ScrollView>
</View>
</View>
);
}
else{
const {orders,navigation} = this.state;
DefaultScreen.navigationOptions = {
title: ''
}
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<View style={styles.header}>
<TouchableOpacity
onPress={() => {
this.props.navigation.openDrawer();
}}
style = {{marginTop:'10%'}}
>
<Icon name="md-menu" size={35} color={'#fff'}/>
</TouchableOpacity>
<Text style={styles.textHeader}>Home</Text>
</View>
<View style={styles.innerContainer}>
<ScrollView style={styles.scrollView}
refreshControl={ <RefreshControl refreshing={this.state.refreshing} onRefresh={this._onRefresh}/>}
>
<Card theme={theme}
>
<Card.Title title="Order List" subtitle="" />
<Card.Content>
{
orders.map((a,b)=>{
return [
<MainOrders key={a.orderID} dName= {a.orderID} note ={a.Note} transType={a.transportType} orderDetails={a}
navigation={this.props.navigation}
/>
]
})
}
</Card.Content>
<Card.Actions>
<Button title="Press me" style={{zIndex:9999}} onPress={()=>{
Alert.alert('Hello World')
}}> Press me</Button>
</Card.Actions>
</Card>
</ScrollView>
</View>
</View>
);
}
}
}
class MainOrders extends React.Component {
constructor() {
super();
}
render() {
return (
<View style={{marginTop:2,marginBottom:2}}>
<Card theme={theme}>
<Card.Title title={this.props.dName} subtitle={this.props.note} />
<Card.Content>
<Text>{this.props.transType}</Text>
</Card.Content>
<Card.Actions>
<Button title="view order" style={{zIndex:9999}} onPress={()=>{
this.props.navigation.navigate('orderDetails',{orderDetails: this.props.orderDetails})
}}> view order</Button>
</Card.Actions>
</Card>
</View>
);
}
}
I tried changing the execution orders,
setting timeout and when I manually filled out the order array was that I realized that the problem is at that point, but I can't see what I'm doing wrong.
"react-native": "0.59.8"
Thanks.
Related
I'm newbie in React-native and I'm confused on how can I pass the parameter to another js file when returning a View, The second problem , The code I used below is when returning home the previous page(login) didn't close or gone and the home didn't view properly. I'm aware using react-nativigation but it's hard for me to implement but is there any other way to direct login when it loads? please need some help for this , here's my code,
Login.js After login from googlesignin when the state loaded it goes to another activity
import { Home } from "../screens"
render() {
return (
<View style={styles.container}>
<GoogleSigninButton
style={{ width: 222, height: 48 }}
size={GoogleSigninButton.Size.Wide}
color={GoogleSigninButton.Color.Dark}
onPress={this.signIn}
/>
{this.state.loaded ?
<View style={{ width: 160, marginTop: 10 }}>
{renderLogin(this)} //return some value
</View>
: <Text>Not signIn</Text>}
</View>
);
}
}
function renderLogin(ts) {
return (
<Home /> // i want to pass value to home js example: 'ts.state.userGoogleInfo.user.photo'
)
}
Whole code in Login.js
import React, { Component } from 'react';
import { View, StyleSheet, ToastAndroid, Button, Text, Image } from "react-native";
import { Home } from "../screens"
import {
GoogleSignin,
GoogleSigninButton,
statusCodes,
} from '#react-native-community/google-signin';
GoogleSignin.configure({
webClientId: '2622122222248-3v21124124124124.apps.googleusercontent.com',
offlineAccess: true, // if you want to access Google API on behalf
});
class Login extends Component {
constructor(props) {
super(props)
this.state = {
userGoogleInfo: {},
loaded: false
}
}
static navigationOptions = {
title: 'Login',
};
signIn = async () => {
try {
console.log("Processing");
await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();
this.setState({
userGoogleInfo: userInfo,
loaded: true
})
console.log(this.state.userGoogleInfo);
console.log(this.state.userGoogleInfo.user.name)
console.log(this.state.userGoogleInfo.user.email)
} catch (error) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
console.log("e 1");
} else if (error.code === statusCodes.IN_PROGRESS) {
console.log("e 2");
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
console.log("e 3");
} else {
console.log(error.message);
}
}
};
render() {
return (
<View style={styles.container}>
<GoogleSigninButton
style={{ width: 222, height: 48 }}
size={GoogleSigninButton.Size.Wide}
color={GoogleSigninButton.Color.Dark}
onPress={this.signIn}
/>
{this.state.loaded ?
<View style={{ width: 160, marginTop: 10 }}>
{renderLogin(this)}
</View>
: <Text>Not signIn</Text>}
</View>
);
}
}
function renderLogin(ts) {
return (
<Home />
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000000',
padding: 15,
},
buttons: {
width: 20
}
});
export default Login;
Home.js
import React from 'react';
import {
StyleSheet,
View,
Text,
ScrollView,
FlatList,
TouchableOpacity,
Image,
ImageBackground,
LogBox
} from 'react-native';
import { PriceAlert, TransactionHistory } from "../components"
import { dummyData, COLORS, SIZES, FONTS, icons, images} from '../constants';
const Home = ({ navigation }) => {
const [trending, setTrending] = React.useState(dummyData.trendingCurrencies)
const [transactionHistory, setTransactionHistory] = React.useState(dummyData.transactionHistory)
function renderHeader(){
const renderItem = ({item, index}) =>(
<TouchableOpacity
style={{
width:155,
paddingVertical:SIZES.padding,
paddingHorizontal:SIZES.padding,
marginLeft: index == 0 ? SIZES.padding : 0,
marginRight: SIZES.radius,
borderRadius: 15,
backgroundColor: COLORS.white
}}
onPress={() => navigation.navigate("CryptoDetail", {currency:item})}
>
{/* Currency*/}
<View style={{ flexDirection:'row'}}>
<View>
<Image
source={item.image}
resizeMode="cover"
style={{
marginTop: 5,
width: 25,
height: 25
}}
/>
</View>
<View style={{marginLeft: SIZES.base}}>
<Text style={{...FONTS.h3}}>{item.currency}</Text>
<Text style={{ color:COLORS.gray, ...FONTS.body3 }}></Text>
</View>
</View>
{/* value*/}
{/* <View style={{ marginTop:SIZES.radius}}> */}
{/* <Text style={{...FONTS.h6}}>₱{item.amount}</Text> */}
{/* <Text style={{color: item.type =="I" ? COLORS.green : COLORS.red, ...FONTS.h5}}>₱{item.amount}</Text> */}
{/* </View> */}
</TouchableOpacity>
)
return(
<View
style={{
width: "100%",
height: 210,
...styles.shadow
}}
>
<ImageBackground
source={images.banner}
resizeMode="cover"
style={{
flex: 1,
alignItems:'center'
}}
>
{/* Header Bar */}
<View
style={{
marginTop:SIZES.padding *1,
width: "100%",
alignItems: "flex-end",
paddingHorizontal: SIZES.padding
}}
>
<TouchableOpacity
style={{
width: 20,
height: 20,
alignItems: "center",
justifyContent:"center"
}}
onPress={() => console.log("Notification on pressed")}
>
<Image
source={icons.notification_white}
resizeMode="contain"
style={{flex: 1}}
/>
</TouchableOpacity>
</View>
{/* Balance */}
<View
style={{
alignItems: 'center',
justifyContent:'center'
}}
>
<Text style={{ color: COLORS.white, ...FONTS.h3}}>Available Balance</Text>
<Text style={{ marginTop:SIZES.base, color:COLORS.white, ...FONTS.h2}}>₱{dummyData.portfolio.balance}</Text>
<Text style={{color:COLORS.white, ...FONTS.body5}}>{dummyData.portfolio.changes} Last 24 hours</Text>
</View>
{/* Trending */}
<View
style={{
position:'absolute',
bottom: "-30%"
}}
>
<Text style={{ marginLeft:SIZES.padding,
color: COLORS.white, ...FONTS.h3 }}>Dashboard</Text>
<FlatList
contentContainerStyle={{marginTop:SIZES.base}}
data={trending}
renderItem={renderItem}
keyExtractor={item => `${item.id}`}
horizontal
showsHorizontalScrollIndicator={false}
/>
</View>
</ImageBackground>
</View>
)
}
function renderAlert(){
return (
<PriceAlert/>
)
}
function renderNotice(){
return (
<View
style={{
marginTop:SIZES.padding-6,
marginHorizontal: SIZES.padding,
padding: 12,
borderRadius:SIZES.radius,
backgroundColor:COLORS.secondary,
...styles.shadow
}}
>
<Text style={{color:COLORS.white, ...FONTS.h4}}>Announcement:</Text>
<Text style={{marginTop:SIZES.base, color:COLORS.white, ...FONTS.body4, lineHeight:18}}>We offer you an application to guide and track your data.
Learn how to use this application by reading instructions and guide.
</Text>
<TouchableOpacity
style={{
marginTop:SIZES.base
}}
onPress={()=> console.log("Learn More")}
>
<Text style={{ textDecorationLine: 'underline',
color:COLORS.green, ...FONTS.h4}}>Learn more
</Text>
</TouchableOpacity>
</View>
)
}
function renderTransactionHistory(){
return (
<TransactionHistory
customContainerStyle={{ ...styles.shadow}}
history={transactionHistory}
/>
)
}
return (
<ScrollView>
<View style={{ flex:1, paddingBottom:130 }}>
{renderHeader()}
{renderAlert()}
{renderNotice()}
{renderTransactionHistory()}
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
shadow: {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.30,
shadowRadius: 4.65,
elevation: 8,
}
})
export default Home;
Apps.js
import React from 'react';
import { Transaction, TevDetail, Login } from "./screens";
import { createStackNavigator } from "#react-navigation/stack";
import { NavigationContainer } from '#react-navigation/native';
import SplashScreen from 'react-native-splash-screen';
import Tabs from "./navigation/tabs";
const Stack = createStackNavigator();
const App = () => {
React.useEffect(() => {
SplashScreen.hide()
}, [])
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false
}}
initialRouteName={'Login'}
>
<Stack.Screen
name="Home"
component={Tabs}
/>
<Stack.Screen
name="TevDetail"
component={TevDetail}
/>
<Stack.Screen
name="Transaction"
component={Transaction}
/>
<Stack.Screen
name="Login"
component={Login}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default App;
I have a problem.
I want after I successfully add product to cart my shopping cart badge will be updated. But I can't setState the itemCart component.
This is code when i add products in cart.
Function _datmon() will do that.
import React, { Component } from 'react';
import {View,Text,StyleSheet,Dimensions,Image, TouchableOpacity,Modal, Button, Alert} from 'react-native';
import { RecyclerListView, DataProvider, LayoutProvider } from "recyclerlistview";
import { Snackbar} from 'react-native-paper';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import AsyncStorage from '#react-native-community/async-storage';
import Home from '../Home';
import 'regenerator-runtime/runtime';
export default class FoodByList extends Component{
constructor(props){
super(props);
this.state={
mang:[],
dataProvider: new DataProvider ((r1,r2)=> r1!==r2),
statusInform:false,
modalVisible: false,
id:'',
gia:'',
mota:'',
soluong:1,
mangmonan:[{
id:'',
soluong:'',
}],
getArr:[],
hide: true,
}
this.home = new Home();
this.homeref = React.createRef();
}
openModalWithItem(item) {
this.setState({
ten: item.ten,
gia: item.gia,
hinhanh: item.hinhanh,
id: item.id,
mota: item.mota,
})
}
layoutProvider = new LayoutProvider(
index => {
return index;
},
(type,dim) => {
dim.width = Dimensions.get('window').width/2;
dim.height = 280;
}
)
_datmon = async()=>{
//Get array availible device
try {
const myArray = await AsyncStorage.getItem('keyOrdermonan');
if (myArray !== null) {
// We have data!!
console.log(JSON.parse(myArray));
}
} catch (error) {
// Error retrieving data
console.log(error);
}
const myArray = await AsyncStorage.getItem('keyOrdermonan');
if(myArray !=null){
this.state.getArr = JSON.parse(myArray);
//Id food currently
const check = {id:this.state.id};
var position = 0;
//Check id avalilabled in cart ?
const police = this.state.getArr.some(getA => getA.id===check.id );
if(police==true){
for(var i =0;i<this.state.getArr.length;i++){
if(this.state.getArr[i].id==this.state.id){
break;
}else{
position+=1;
}
}
this.state.getArr[position].soluong += this.state.soluong;
this.setState({mangmonan: this.state.getArr});
this.homeref.setSizeCart(this.state.mangmonan.length);
console.log('Completely udrage quanity');
}
else if(police==false){
this.setState({mangmonan: [{id: this.state.id,
soluong: this.state.soluong,
}].concat(this.state.getArr)});
this.homeref.setSizeCart(this.state.mangmonan.length);
}
}else{
this.setState({mangmonan: [{id: this.state.id,
soluong: this.state.soluong,
}]});
this.homeref.setSizeCart(this.state.mangmonan.length);
}
// Add new cart
try {
await AsyncStorage.setItem('keyOrdermonan', JSON.stringify(this.state.mangmonan));
// await AsyncStorage.removeItem('keyOrdermonan');
this.setState({modalVisible:false,soluong:1});
Alert.alert(
"Thành công",
"Đặt món thành công, vui lòng kiểm tra giỏ hàng",
[
{
text: "Kiểm tra giỏ hàng",
onPress: ()=>{this.props.navigation.navigate('cart')}
},
{
text: "Tiếp tục đặt món",
style:'cancel'
},
]
);
} catch (error) {
// Error saving data
console.log(error);
}
}
getPriceVND = (giatri) => {
const parts = giatri.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const gia = parts.join(".");
return gia;
}
rowrender = (type,item) => {
return(
<View style={styles.bgitem}>
<TouchableOpacity style={styles.wrapperitem} onPress={()=> {this.setState({modalVisible:true}),this.openModalWithItem(item)}}>
<View style={styles.wrapperimg}>
<Image source={{ uri: item.hinhanh }} style={styles.img}/>
</View>
</TouchableOpacity>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold' }}>Tên món ăn:</Text>
<Text style={styles.under}>{item.ten}</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold' }}>Giá: </Text>
<Text style={styles.under}>{this.getPriceVND(item.gia)}đ</Text>
</View>
</View>
)
}
componentDidMount(){
//set lại tittle bar
this.props.navigation.setOptions({title:this.props.route.params.tendanhmuc});
fetch("http://192.168.43.25/DemoJWT/getMonAnByList.php",{
method:'POST',
headers: {
"Accept":"application/json",
"Content-Type":"application/json"
},
body: JSON.stringify({
"IDDANHMUC" : this.props.route.params.id,
})
})
.then((reponse)=>reponse.json())
.then((reponseJson)=>{
if(reponseJson==""){
this.setState({statusInform:true});
}else{
this.setState({
mang:reponseJson,
dataProvider:this.state.dataProvider.cloneWithRows(reponseJson),
})
}
})
.catch((err)=>{
console.log(err);
})
}
render(){
return(
<View style={styles.wrapper}>
{!this.state.hide && <Home ref={this.homeref} />}
{ !this.state.dataProvider.getSize()==0 &&
<RecyclerListView
layoutProvider={this.layoutProvider}
rowRenderer={this.rowrender}
dataProvider = {this.state.dataProvider}
/>
}
{/* Thông báo khi không có món */}
<Snackbar
visible={this.state.statusInform}
onDismiss={()=>{this}}
action={{
label: 'Trở về',
onPress: () => {
this.props.navigation.goBack()
},
}}>
Hiện nhà hàng chưa có các món ăn này.
Mong quý khách thông cảm !
</Snackbar>
{/* Thông báo khi không có món */}
{/* Hiển thị khi nhấn chi tiết món ăn để đặt hàng */}
<View>
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
>
<View style={styles.modalView}>
<View style={styles.wrapperimgModal}>
<Image source={{ uri: this.state.hinhanh }} style={styles.imgModal}/>
<View style={styles.wrappername,{marginTop:15}}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Tên món ăn:</Text>
<Text >{this.state.ten}</Text>
</View>
<View style={{ flexDirection:'column' }}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Giá: </Text>
<Text>{this.getPriceVND(this.state.gia)} đ / 1 phần</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Mô tả:</Text>
<Text>{this.state.mota}</Text>
</View>
<View style={styles.wrappername}>
<Text style={{ fontWeight:'bold',fontSize:18, }}>Số lượng:</Text>
<View style={{ flexDirection:'row',marginLeft:0,marginTop:10 }}>
<TouchableOpacity style={styles.decrease} onPress={()=>{
if(this.state.soluong==1){
console.log('Không giảm nữa');
}else{
this.setState({soluong:this.state.soluong-1})
}
}}>
<MaterialCommunityIcons name='minus-circle' color="black" size={24} />
</TouchableOpacity>
<Text>{this.state.soluong}</Text>
<TouchableOpacity style={styles.increase} onPress={()=>{
if(this.state.soluong==15){
console.log('Không tăng nữa');
}
else{
this.setState({soluong:this.state.soluong+1})
}
}}>
<MaterialCommunityIcons name='plus-circle' color="black" size={24} />
</TouchableOpacity>
</View>
</View>
</View>
<View style={styles.totalbtn}>
<View style={styles.btn}>
<Button
title="Hủy"
onPress={()=>{this.setState({modalVisible:false,soluong:1})}}
/>
</View>
<View style={styles.btn2}>
<Button title="Đặt ngay"
onPress={()=>{this._datmon()}}
/>
</View>
</View>
</View>
</Modal>
</View>
{/* Hiển thị khi nhấn chi tiết món ăn để đặt hàng */}
</View>
)
}
}
const styles = StyleSheet.create({
wrapper:{
flex:1,
},
wrapperitem:{
flex:1,
},
title:{
fontSize:30,
padding:10,
fontWeight:'bold',
},
bgitem:{
flex:1,
flexDirection:'column',
padding:10,
margin:10,
borderWidth:1,
borderRadius:15,
backgroundColor:'#dddddd',
},
wrapperimg:{
width:"100%",
height:180,
alignItems:'center',
padding:5,
},
wrapperimgModal:{
width:"100%",
height:370,
padding:5,
marginLeft:10,
},
img:{
width:'80%',
height:100,
borderRadius:10,
},
imgModal:{
width:'100%',
height:150,
borderRadius:10,
},
wrappername:{
flexDirection:'column',
},
under:{
paddingLeft:10,
},
modalView: {
margin: 20,
marginTop:100,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
totalbtn:{
flexDirection:'row',
alignItems:'center',
justifyContent:'center'
},
btn:{
width:90,
marginRight:10,
},
btn2:{
width:90,
marginLeft:10,
},
decrease:{
marginRight:10,
},
increase:{
marginLeft:10
}
})
Still here is your code setSizeCart() in class component Home.js :
import React, { Component } from "react";
import {StyleSheet, Alert,View, StatusBar,Linking, Text} from "react-native"
import AsyncStorage from '#react-native-community/async-storage';
import HomeScreen from "./Screen/HomeScreen";
import FavouriteScreen from "./Screen/FavouriteScreen";
import ProfileScreen from "./Screen/ProfileScreen";
import CartScreen from "./Screen/CartScreen";
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { Appbar, Snackbar,Badge } from 'react-native-paper';
import NetInfo from "#react-native-community/netinfo";
import {createDrawerNavigator} from "#react-navigation/drawer"
import { DrawerActions } from '#react-navigation/native';
import SettingScreen from "./Screen/SettingScreen";
import BookingScreen from "./Screen/BookingScreen";
import FullFood from "./Screen/FullFood";
import 'regenerator-runtime/runtime';
const Drawer = createDrawerNavigator();
export default class Home extends Component{
_isMounted = false;
constructor(props){
super(props);
this.state={
token:"",
ten:"",
statusInform:false,
searchQuery:"",
getMangAsync:[],
itemcart: 0 ,
}
this.setSizeCart = this.setSizeCart.bind(this);
}
setSizeCart (bien){
try {
this.setState({ itemcart: bien });
console.log("set thành công");
} catch (error) {
console.log(error);
}
}
_getasyc = async()=>{
try {
const key = await AsyncStorage.getItem("keyOrdermonan");
if(key!==null){
this.setState({getMangAsync:JSON.parse(key)});
this.setState({itemcart:this.state.getMangAsync.length});
}
} catch (error) {
console.log(error)
}
}
checkInternet(){
NetInfo.fetch("http://192.168.43.25/DemoJWT/checkToken.php")
.then(state=>{
console.log(state.isConnected)
if(state.isConnected==false){
this.setState({statusInform:true})
}
})
}
componentDidMount(){
this._isMounted = true;
if(this._isMounted){
this.checkInternet();
this._getasyc();
}
}
componentWillUnmount(){
this._getasyc();
// console.log("đã"+ this._isMounted)
}
_logout = async() =>{
try {
await AsyncStorage.removeItem("keyToken");
Alert.alert("Đăng xuất");
this.props.navigation.navigate('login');
} catch (error) {
console.log(error)
}
}
contact(){
Alert.alert(
"Liên hệ với chúng tôi",
"Bạn có muốn hay không?",
[
{
text: "Hủy",
style:'cancel'
},
{
text: "Đồng ý",
onPress: ()=>Linking.openURL('tel:$+84705982473')
}
]
)
}
render(){
// const {ten} = this.props.route.params
return(
<View style={{ flex:1 }}>
<StatusBar backgroundColor='#555555' barStyle="light-content" />
<Appbar style={styles.appbar}>
<Appbar.Action icon="format-list-bulleted" onPress={()=>(this.props.navigation.dispatch(DrawerActions.openDrawer()))}/>
<Appbar.Content title="GREAT FOOD" />
<Badge
visible={this.state.itemcart && this.state.itemcart >0}
size={17}
style={{ position: 'absolute', top: 5, right: 55 }}>{this.state.itemcart}</Badge>
<Appbar.Action icon="cart" onPress={()=>{this.props.navigation.navigate('cart')}}/>
<Appbar.Action icon="phone-in-talk" onPress={()=>{this.contact()}}/>
</Appbar>
<Drawer.Navigator
overlayColor="transparent"
>
<Drawer.Screen name ="home" component={HomeScreen}
options={{
drawerLabel:"Menu",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="home" color={color} size={26} />
), }}
/>
<Drawer.Screen name="profile" component={ProfileScreen}
options={{
drawerLabel:"Hồ sơ",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="account-circle" color={color} size={26} />
), }}
/>
<Drawer.Screen name="fullfood" component={FullFood}
options={{
drawerLabel:"Tất cả món ăn",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="food" color={color} size={26} />
), }}
/>
<Drawer.Screen name= "favourite" component={FavouriteScreen}
options={{
drawerLabel:"Yêu thích",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="heart-pulse" color={color} size={26} />
), }}
/>
<Drawer.Screen name= "booking" component={BookingScreen}
options={{
drawerLabel:"Đặt bàn",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="table-furniture" color={color} size={26} />
), }}
/>
<Drawer.Screen name="cart" component={CartScreen}
options={{
drawerLabel:"Giỏ hàng",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="cart" color={color} size={26} />
), }}
/>
<Drawer.Screen name="setting" component={SettingScreen}
options={{
drawerLabel:"Cài đặt",
drawerIcon:({color})=>(
<MaterialCommunityIcons name="wrench-outline" color={color} size={26} />
), }}
/>
</Drawer.Navigator>
<Snackbar
visible={this.state.statusInform}
onDismiss={()=>{this}}
action={{
label: 'Tắt',
onPress: () => {
this.setState({statusInform:false})
},
}}>
Vui lòng kiểm tra kết nối.
</Snackbar>
</View>
)
}
}
const styles = StyleSheet.create({
wrapper:{
flex:1,
justifyContent:"center",
alignItems:'center',
},
logout:{
marginTop:50,
},
appbar:{
backgroundColor:'#555555'
},
})
And I have been received warning is:
Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Home component.
Can anyone help me!
So one small thing you are missing here is that,
Creating a new component using the new keyword is not going to mount that component into the render tree.
You should include it inside the render function of your FoodByList like this
<Home ref={this.homeRef} />
Then, in the constructor of your FoodByList component, create the homeRef using
this.homeRef = React.createRef();
More on React.createRef in this article.
Basically assigning a ref to the Home component inside the render of FoodByList gives you the ability to call the functions inside the Home component.
Next, in Home component's constructor use this.setSizeCart = this. setSizeCart.bind(this) or else convert the setSizeCart function into an arrow function like this
setSizeCart = (bien) => {
try {
this.setState({ itemcart: bien });
console.log("set successfully");
} catch (error) {
console.log(error);
}
}
So now, instead of doing
this.home.setSizeCart(this.state.mangmonan.length)
you should be doing
this.homeRef.current.setSizeCart(this.state.mangmonan.length)
I am new to react native and was trying to display some data into a react component (preferably cards) but for now FlatList will work. I was unable to destructure the data and display it. How should it be done?
import React,{useState,useEffect} from 'react';
import { StyleSheet,Modal, View ,Text , ScrollView, Alert} from 'react-native';
import {IconButton ,Appbar, Card, TextInput ,Button ,
} from 'react-native-paper';
import firebase from './config';
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Setting a timer']);
export default function PlantATree(){
const [modalVisible, setModalVisible] = useState(false);
const [name,setName]=useState('');
const [title, setTitle]=useState('');
const [description, setDescription]=useState('');
const [data, setmyData]=useState([])
const savePost = () =>{
firebase.database()
.ref('posts')
.push({
"id":Math.random(),
"name":name,
"title":title,
"description":description,
})
setTimeout(()=>{
Alert.alert("Your post is saved successfully :D")
},1000)
}
useEffect(()=>{
const data = firebase.database().ref("posts");
data.on("value", datasnap =>{
//console.log(Object.values(datasnap.val()));
if(datasnap.val()){
setmyData(datasnap.val());
}
})
},[]);
//console.log(data);
const src= Object.keys(data);
console.log("Hi",src);
return (
<ScrollView>
<Appbar.Header>
<Appbar.Content title="Plant a tree Initiative"/>
</Appbar.Header>
<IconButton
icon="plus"
color="crimson"
size={30}
onPress={() => setModalVisible(true)}
/>
<View style={styles.centeredView}>
{/*Modal Content Starts Here*/}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
>
<View style={styles.centeredView}>
<ScrollView style={styles.modalView}>
<Appbar.Header style={{ padding:10}}>
<Appbar.Content title="Share your story.." />
</Appbar.Header>
<Card>
<Card.Content >
<View style={{marginLeft:0,marginRight:0,
}}>
<Card >
<Card.Content>
<TextInput
style={{}}
label="Your name...."
mode="outlined"
value={name}
onChangeText={text =>{ setName(text)}}
/>
<TextInput
style={{}}
label="Story Title...."
mode="outlined"
value={title}
onChangeText={text =>{ setTitle(text)}}
/>
<TextInput
style={styles.formcomponents}
label="Share your thoughts...."
mode="outlined"
multiline={true}
numberOfLines={8}
value={description}
onChangeText={text =>{ setDescription(text)}}
/>
</Card.Content>
</Card>
</View>
<Card>
<Button mode="contained" style={{margin:20}}
onPress={savePost}>
post
</Button>
<Button mode="contained" style={{margin:20,backgroundColor:'crimson'}} onPress={() => setModalVisible(!modalVisible)}>
close
</Button>
</Card>
</Card.Content>
</Card>
</ScrollView>
</View>
</Modal>
</View>
<View>
{/* DATA FROM FIREBASE */}
<Text>{data?.description}</Text>
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
centeredView: {
marginTop: 45,
marginBottom:45,
},
modalView: {
backgroundColor: "white",
borderRadius: 20,
marginTop:70,
marginBottom:20,
marginRight:20,
marginLeft:20,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
});
Data Format:
Object {
"-MQXpKu8Zh1PCVsBLquO": Object {
"description": "Good story.",
"id": 0.8842625745597491,
"name": "Subhodeep",
"title": "Story 1 ",
},
"-MQXpRXS5_6m6YTZ39e0": Object {
"description": "Good story 2.",
"id": 0.8767685757714464,
"name": "Sanjoy",
"title": "Story 2",
},
"-MQXpX7ku-41CreQ8SOP": Object {
"description": "Good story 3.
",
"id": 0.9976208307830834,
"name": "Sanchari",
"title": "Story 3",
},
Since the data from Firebase consists of multiple nodes, you'll need to iterate over the results and map each child to a new component.
I typically find that easiest by first converting the snapshot to an array (instead of an Object) when it is loaded:
useEffect(()=>{
const data = firebase.database().ref("posts");
data.on("value", datasnap =>{
let data = [];
datasnap.forEach((childsnap) => {
let val = childsnap.val();
val["$key"] = childsnap.key;
data.push(val);
})
setmyData(data);
})
},[]);
Then in the rendering code we can loop over this data array and render a component for each item:
data.map((item) => <Text id={item["$key"]}>{item.description}</Text>)
There might be some syntax errors in the rendering, but the overall flow should be clear from this.
Here, I am fetching data from firebase and then trying to output it in a tinder card like format. My code is as follows -
import React from 'react';
import { View, ImageBackground, Text, Image, TouchableOpacity } from 'react-native';
import CardStack, { Card } from 'react-native-card-stack-swiper';
import City from '../components/City';
import Filters from '../components/Filters';
import CardItem from '../components/CardItem';
import styles from '../assets/styles';
import Demo from '../assets/demo';;
import {db} from '../config/config';
class Home extends React.Component {
constructor (props) {
super(props);
this.state = ({
items: [],
isReady: false,
});
}
componentWillMount() {
let items = [];
db.ref('cards').once('value', (snap) => {
snap.forEach((child) => {
let item = child.val();
item.id = child.key;
items.push({
name: child.val().pet_name,
description: child.val().pet_gender,
pet_age: child.val().pet_age,
pet_breed: child.val().pet_breed,
photoUrl: child.val().photoUrl,
});
});
//console.log(items)
this.setState({ items: items, isReady: true });
console.log(items);
});
}
componentWillUnmount() {
// fix Warning: Can't perform a React state update on an unmounted component
this.setState = (state,callback)=>{
return;
};
}
render() {
return (
<ImageBackground
source={require('../assets/images/bg.png')}
style={styles.bg}
>
<View style={styles.containerHome}>
<View style={styles.top}>
<City />
<Filters />
</View>
<CardStack
loop={true}
verticalSwipe={false}
renderNoMoreCards={() => null}
ref={swiper => {
this.swiper = swiper
}}
>
{this.state.items.map((item, index) => (
<Card key={index}>
<CardItem
//image={item.image}
name={item.name}
description={item.description}
actions
onPressLeft={() => this.swiper.swipeLeft()}
onPressRight={() => this.swiper.swipeRight()}
/>
</Card>
))}
</CardStack>
</View>
</ImageBackground>
);
}
}
export default Home;
I am fetching data and storing it in an array called items[]. Console.log(items) gives me the following result:
Array [
Object {
"description": "male",
"name": "dawn",
"pet_age": "11",
"pet_breed": "golden retriever",
"photoUrl": "picture",
},
Object {
"description": "Male",
"name": "Rambo",
"pet_age": "7",
"pet_breed": "German",
"photoUrl": "https://firebasestorage.googleapis.com/v0/b/woofmatix-50f11.appspot.com/o/pFkdnwKltNVAhC6IQMeSapN0dOp2?alt=media&token=36087dae-f50d-4f1d-9bf6-572fdaac8481",
},
]
Furthermore, I want to output my data in a card like outlook so I made a custom component called CardItem:
import React from 'react';
import styles from '../assets/styles';
import { Text, View, Image, Dimensions, TouchableOpacity } from 'react-native';
import Icon from './Icon';
const CardItem = ({
actions,
description,
image,
matches,
name,
pet_name,
pet_gender,
pet_age,
onPressLeft,
onPressRight,
status,
variant
}) => {
// Custom styling
const fullWidth = Dimensions.get('window').width;
const imageStyle = [
{
borderRadius: 8,
width: variant ? fullWidth / 2 - 30 : fullWidth - 80,
height: variant ? 170 : 350,
margin: variant ? 0 : 20
}
];
const nameStyle = [
{
paddingTop: variant ? 10 : 15,
paddingBottom: variant ? 5 : 7,
color: '#363636',
fontSize: variant ? 15 : 30
}
];
return (
<View style={styles.containerCardItem}>
{/* IMAGE */}
<Image source={image} style={imageStyle} />
{/* MATCHES */}
{matches && (
<View style={styles.matchesCardItem}>
<Text style={styles.matchesTextCardItem}>
<Icon name="heart" /> {matches}% Match!
</Text>
</View>
)}
{/* NAME */}
<Text style={nameStyle}>{name}</Text>
{/* DESCRIPTION */}
{description && (
<Text style={styles.descriptionCardItem}>{description}</Text>
)}
{/* STATUS */}
{status && (
<View style={styles.status}>
<View style={status === 'Online' ? styles.online : styles.offline} />
<Text style={styles.statusText}>{pet_age}</Text>
</View>
)}
{/* ACTIONS */}
{actions && (
<View style={styles.actionsCardItem}>
<View style={styles.buttonContainer}>
<TouchableOpacity style={[styles.button, styles.red]} onPress={() => {
this.swiper.swipeLeft();
}}>
<Image source={require('../assets/red.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.orange]} onPress={() => {
this.swiper.goBackFromLeft();
}}>
<Image source={require('../assets/back.png')} resizeMode={'contain'} style={{ height: 32, width: 32, borderRadius: 5 }} />
</TouchableOpacity>
<TouchableOpacity style={[styles.button, styles.green]} onPress={() => {
this.swiper.swipeRight();
}}>
<Image source={require('../assets/green.png')} resizeMode={'contain'} style={{ height: 62, width: 62 }} />
</TouchableOpacity>
</View>
</View>
)}
</View>
);
};
export default CardItem;
The problem is when I try to pass the data in my items[] array, the cardItem component just doesnt work. To dry-run, I used a sample demo array and when I use the Demo array, my component works just fine. What am I doing wrong? I have been tinkering with this problem for quite a while now. Any help whatsoever would be appreciated.
I am pretty new to React Native, so if the question seems stupid i am sorry in advance, i have been trying for hours to get this to work before asking this question.
I am trying to pass data from a text input to the next screen using firebase database.
I keep getting the error JSON Parse error: Unexpected identifier "undefined", I have attached below my two files, one with the text input (InputForm.js) and the other one which i want to show that data on the screen (ASTConfig1screen)
If anyone can help with this you really are a superstar!
InputForm.js
import React, { Component } from 'react';
import { StyleSheet, ScrollView, ActivityIndicator, View, TextInput } from 'react-native';
import { Button } from 'react-native-elements';
import firebase from '../Firebase';
import { withNavigation } from 'react-navigation';
class InputForm extends Component {
constructor() {
super();
this.ref = firebase.firestore().collection('boards');
this.state = {
name: '',
inventoryclass: '',
outlet: '',
isLoading: false,
};
}
updateTextInput = (text, field) => {
const state = this.state
state[field] = text;
this.setState(state);
}
saveBoard() {
this.setState({
isLoading: true,
});
this.ref.add({
name: this.state.name,
inventoryclass: this.state.inventoryclass,
outlet: this.state.outlet,
}).then((docRef) => {
this.setState({
name: '',
outlet: '',
inventoryclass: '',
isLoading: false,
});
this.props.navigation.navigate('ASTConfig1');
})
.catch((error) => {
console.error("Error adding document: ", error);
this.setState({
isLoading: false,
});
});
}
render() {
if(this.state.isLoading){
return(
<View style={styles.activity}>
<ActivityIndicator size="large" color="#ffa500"/>
</View>
)
}
return (
<ScrollView style={styles.container}>
<View style={styles.subContainer}>
<TextInput style={styles.inputtext}
placeholder={'Name'}
placeholderTextColor="white"
value={this.state.name}
onChangeText={(text) => this.updateTextInput(text, 'name')}
/>
</View>
<View style={styles.subContainer}>
<TextInput style={styles.inputtext}
multiline={true}
numberOfLines={4}
placeholder={'Inventory Class'}
placeholderTextColor="white"
value={this.state.inventoryclass}
onChangeText={(text) => this.updateTextInput(text, 'inventoryclass')}
/>
</View>
<View style={styles.subContainer}>
<TextInput style={styles.inputtext}
placeholder={'Outlet'}
placeholderTextColor="white"
value={this.state.outlet}
onChangeText={(text) => this.updateTextInput(text, 'outlet')}
/>
</View>
<View style={styles.button}>
<Button
large
leftIcon={{name: 'save'}}
title='Save'
onPress={() => this.saveBoard()} />
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20
},
subContainer: {
flex: 1,
marginBottom: 20,
padding: 5,
borderBottomWidth: 2,
borderBottomColor: '#CCCCCC',
},
inputtext: {
color: 'white',
fontSize: 20
},
activity: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
}
})
export default withNavigation(InputForm);
and this is where i would like to show the data on this screen
ASTConfig1.js
import React from 'react';
import {
View,
Text,
StyleSheet,
Button,
ImageBackground,
StatusBar,
SafeAreaView,
TextInput,
ScrollView,
UIManager,
ActivityIndicator
}
from 'react-native';
import {AccordionList} from "accordion-collapse-react-native";
import { Separator } from 'native-base';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
import firebase from '../Firebase';
import Logo from '.././components/Logo';
import Colors from '.././constants/Colors';
import Search from '.././components/Search';
import InputForm from '.././components/InputForm';
class ASTConfig1Screen extends React.Component {
static navigationOptions = {
title: 'ASTConfig1',
};
constructor(props) {
super(props);
this.state= {
isLoading: true,
board: {},
key: '',
status:true,
text: '',
list:[
{
title: 'Getting Started',
body: 'React native Accordion/Collapse component, very good to use in toggles & show/hide content'
},
{
title: 'Components',
body: 'AccordionList,Collapse,CollapseHeader & CollapseBody'
},
{
title: 'Test',
body: 'AccordionList,Collapse,CollapseHeader & CollapseBody'
}
],
}
}
componentDidMount() {
const { navigation } = this.props;
const ref = firebase.firestore().collection('boards').doc(JSON.parse(navigation.getParam('boardkey')));
ref.get().then((doc) => {
if (doc.exists) {
this.setState({
board: doc.data(),
key: doc.id,
isLoading: false
});
} else {
console.log("No such document!");
}
});
}
_head(item){
return(
<Separator bordered style={{alignItems:'center'}}>
<Text>{item.title}</Text>
</Separator>
);
}
_body(item){
return (
<View style={{padding:10}}>
<Text style={{textAlign:'center'}}>{item.body}</Text>
</View>
);
}
ShowHideTextComponentView = () =>{
if(this.state.status == true)
{
this.setState({status: false})
}
else
{
this.setState({status: true})
}
}
render() {
if(this.state.isLoading){
return(
<View style={styles.activity}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
)
}
return (
<View style={styles.screen}>
<ImageBackground
source={require('.././assets/Img/BackGround2.png')}
style={styles.background}>
</ImageBackground>
<SafeAreaView>
<View style={{flex: 1, justifyContent: 'space-between', width: wp('80%')}}>
<View style={styles.logotop}>
<Logo/>
</View>
<View style={styles.editstock}>
<Text style={styles.editstocktext}>EDIT STOCK LIST:</Text>
</View>
{/*Start of 3 buttons Firebase*/}
<View style={styles.three}>
<View style={styles.edit1}>
<Text style={styles.textheader}>{this.state.board.name}</Text>
<Button style={styles.edit} title='Edit' ></Button>
</View>
<View style={{padding: 3}}></View>
<View style={styles.edit2}>
<Text style={styles.text}>{this.state.board.inventoryclass}</Text>
<Button style={styles.edit} title='Edit' ></Button>
</View>
<View style={styles.edit3}>
<Text style={styles.text}>{this.state.board.outlet}</Text>
<Button style={styles.edit} title='Edit' ></Button>
</View>
</View>
{/*End of 3 buttons Firebase*/}
{/*Start of AccordionList*/}
<ScrollView>
<View style={styles.middle}>
<AccordionList
list={this.state.list}
header={this._head}
body={this._body}
/>
</View>
</ScrollView>
{/*End of AccordionList*/}
{/*Start of Search*/}
<View>
{
this.state.status ? null : <View style={styles.bottom}>
<Text style={styles.textbottom}>SEARCH FOR NEW ITEMS:</Text>
<Search />
</View>
}
<Button title="ADD" onPress={this.ShowHideTextComponentView} />
</View>
</View>
</SafeAreaView>
</View>
);
};
};
{/*End of Search*/}
export default ASTConfig1Screen;
but it returns the error - Error adding document: [SyntaxError: SyntaxError: SyntaxError: JSON Parse error: Unexpected identifier "undefined"
in inputform.js saveBoard function you should
this.props.navigation.navigate('Details', {
'ASTConfig1': docRef
});
and remove JSON.parse form other file