Hi everyone i have a problem styling every item present in a flatlist. i find on stackoverflow that you have to use index in the render item but in the render item i have a component that contains all of my items .
What i wanted to reach is this result :
here is my code in the home component:
import React, {useEffect, useState} from 'react';
import {
FlatList,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import {Audio, Book} from '../types';
import customData from '../books.json';
import BookBox from '../components/BookBox';
import Menu from 'react-native-vector-icons/Entypo';
import Glass from 'react-native-vector-icons/Entypo';
export default function HomeScreen() {
const [books, setBooks] = useState<Book[]>([]);
const [audio, setAudio] = useState<Audio[]>([]);
const [selected, setSelected] = useState(false);
const [selectedAudio, setSelectedAudio] = useState(false);
useEffect(() => {
setBooks(customData);
}, []);
const renderBooks = ({item}: {item: Book}) => <BookBox book={item} />;
return (
<ScrollView nestedScrollEnabled={true} style={styles.scrollContainer}>
<View style={styles.searchContainer}>
<Menu name={'menu'} size={30} color={'black'} />
<Text style={styles.textSearch}>All Books</Text>
<Glass name={'magnifying-glass'} size={30} color={'black'} />
</View>
<View style={styles.AudioOrEbookContainer}>
<Pressable
onPress={() => setSelected(!selected)}
style={{backgroundColor: selected ? 'white' : 'transparent'}}>
<View style={styles.btn}>
<Text>Ebook</Text>
</View>
</Pressable>
<Pressable
style={{backgroundColor: selectedAudio ? 'white' : 'transparent'}}>
<View style={styles.btn}>
<Text>Audiobook</Text>
</View>
</Pressable>
</View>
<View style={styles.container}>
<FlatList
data={books}
keyExtractor={item => item.id?.toString()}
renderItem={renderBooks}
numColumns={2}
/>
</View>
</ScrollView>
);
}
here is my code in BookBox component:
import {Text, Image, StyleSheet, View, TouchableHighlight} from 'react-native';
import React from 'react';
import {Book} from '../types';
import {useNavigation} from '#react-navigation/native';
interface Props {
book: Book;
}
export default function BookBox({book}: Props) {
const {
author,
country,
imageLink,
language,
link,
pages,
title,
year,
overview,
vote,
} = book;
const navigation = useNavigation();
return (
<View style={styles.container}>
{imageLink && (
<TouchableHighlight
onPress={() =>
navigation.navigate('SingleBook', {
title,
year,
pages,
link,
language,
imageLink,
country,
author,
overview,
vote,
})
}>
<Image
style={styles.image}
source={{
uri: `${imageLink}`,
}}
/>
</TouchableHighlight>
)}
{!imageLink && <Text>immagine mancante</Text>}
<View style={styles.wrap}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.title}>{author}</Text>
</View>
</View>
);
}
i'm trying to render items with unique style like in the image above.. can you help me? thank you in avance
So, numColumns of FlatList cannot help you to achieve the behavior you want. This is because masonry are not supported by this property, in other words, numColumns sets the same height for every item at the same line. As a resort to implementing this behavior you can check this lib: https://github.com/hyochan/react-native-masonry-list
Related
I am trying to make a Login page with Phone Authentication to use React-Native-Firebase sdk and I receive OTP through sms and when I confirm the received OTP ,I got a error that: [Error: [auth/unknown] Cannot create PhoneAuthCredential without either verificationProof, sessionInfo, temporary proof, or enrollment ID.]
I am using-
React:18.0.0
React-Native: 0.69.1
React-Native-Firebase:^15.1.1
My code is-
import React, {useState} from 'react';
import {
View,
Text,
StyleSheet,
Image,
TextInput,
TouchableOpacity,
Alert,
} from 'react-native';
import PhoneInput from 'react-native-phone-number-input';
import auth from '#react-native-firebase/auth';
const Login = () => {
const [PhoneNumber, setPhoneNumber] = useState('');
const [otpInput, setOtpInput] = useState('');
const [confirmData, setConfirmData] = useState('');
const sendOtp = async () => {
try {
const responce = await auth().signInWithPhoneNumber(PhoneNumber);
setConfirmData(responce);
console.log(responce);
Alert.alert('Otp is sent please varify it');
} catch (error) {
console.log(error);
}
}
const submitOtp = async () => {
try {
const responce = await confirmData.confirm(otpInput);
console.log(responce);
Alert.alert('Your Number is verified');
} catch (error) {
console.log(error);
}
}
return (
<View>
<View style={styles.con}>
<Text style={styles.container}>Login Screen</Text>
<Image source={require('../assets/logo.png')} style={styles.image} />
</View>
<View style={styles.inputContainer}>
<Text style={styles.labels}>Phone Number:</Text>
<PhoneInput
style={styles.inputStyle}
defaultValue={PhoneNumber}
defaultCode="DM"
layout="first"
keyboardType="number-pad"
onChangeFormattedText={text => setPhoneNumber(text)}
onChangeText={(value) => setPhoneNumber(value)}
/>
</View>
<View>
<TouchableOpacity
style={styles.buttonStyle}>
<Text style={styles.buttonText}>Verify</Text>
</TouchableOpacity>
</View>
<View style={styles.otpContainer}>
<TextInput
style={styles.otpStyle}
placeholder="Enter OTP"
autoCapitalize="none"
secureTextEntry={true}
onChangeText={(value) => setOtpInput(value)}/>
</View>
<View>
<TouchableOpacity style={styles.continueStyle}>
<Text
style={styles.buttonText}
onPress={() => submitOtp()}>
Continue
</Text>
</TouchableOpacity>
</View>
</View>
);
};
export default Login;
So im trying to make a todo list app and making the fucntion to add a doc to firebase. However, when i do that expo says the async storage has been deprecated and that there is a unhandled promise rejection
my code in my app:
import React, { useEffect } from 'react';
import {useState} from "react"
import { SafeAreaView, Text, View, Button, TouchableOpacity, Modal, StyleSheet,Pressable, TextInput } from 'react-native';
import { collection, doc, setDoc, query, getDocs, onSnapshot, addDoc, orderBy, limit, Timestamp, where} from "firebase/firestore";
import {db} from "../firebase"
import { signPlsOut } from '../firebase';
import { auth } from '../firebase';
import AsyncStorage from '#react-native-async-storage/async-storage';
export const Dashboard = () => {
const {uid, photoURL, displayName} = auth.currentUser;
const projectsref = collection(db, "projects");
const [modalVisible, setModalVisible] = useState(false);
const [projects, setProjects] = useState([])
const [desc, setDesc] = useState("");
const [title, setTitle] = useState("");
async function handleAddTask () {
try {
await addDoc(projectsref, {
title: title,
desc: desc,
createdAt: Timestamp.fromDate(new Date()),
uid: uid,
})
setTitle("")
setDesc("")
setModalVisible(false)
}
catch(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
// ADD THIS THROW error
throw error;
}
}
return (
<SafeAreaView>
<View style={{
margin: 20
}}>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Add task:</Text>
<View style={{marginBottom: 20}}>
<TextInput placeholder='title' value={title} onChange={(e) => setTitle(e.target.value)}></TextInput>
<TextInput placeholder='description' value={desc} onChange={(e) => setDesc(e.target.value)}></TextInput>
</View>
<Button title='submit todo' onPress={handleAddTask}></Button>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Text style={styles.textStyle}>Cancel</Text>
</Pressable>
</View>
</View>
</Modal>
<Text style={{fontSize: 20, fontWeight: "500"}}>Welcome,</Text>
<Text style={{fontSize: 27, fontWeight: "700"}}>{auth.currentUser.email}</Text>
<View style={{marginTop: 30}}>
<Text style={{fontSize: 40, fontWeight: "700", color: "#0404"}}>Create Task</Text>
<TouchableOpacity>
<View style={{
backgroundColor: "orange",
borderRadius: "20px"
}}>
<Pressable
style={[styles.button, styles.buttonOpen]}
onPress={() => setModalVisible(true)}
>
<Text style={styles.textStyle}>Add task</Text>
</Pressable>
</View>
</TouchableOpacity>
</View>
<Button title="signout" onPress={signPlsOut}></Button>
</View>
</SafeAreaView>
);
};
error:
async sotrage has been extracted and will be removed in a future release, in addition to the unhandled promise rejection error
Are you able to actually add the doc to firebase? Some more context would be helpful in what you're trying to do. Is you code above completely unsucessful and you are getting errors? Or are you simply trying to clear errors.
If you are just trying to get rid of the unhandled promise rejection. I ran into a similar error and I found where in the Firebase app node_module where the call out was being for async storage. For me to get rid of a similar error i did two steps:
First, i installed the new react native async storage module:
npm install #react-native-async-storage/async-storage
Next, i had to update firebase app module, in the following file, to point to the appropriate API within my expo app to point to this new react native async storage module.
./node_modules/#firebase/app/dist/index.rn.cjs.js
I had to adjust this bit of code in this file:
var AsyncStorage = require('#react-native-async-storage/async-storage').AsyncStorage;
firebase.INTERNAL.extendNamespace({
INTERNAL: {
reactNative: {
AsyncStorage: AsyncStorage
}
}
});
The above code previously called to "react" i believe, i just needed to update it to specifically call to "#react-native-async-storage/async-storage". And this solved my problem.
I am trying to use Async Storage in react native expo cli to use login credentials even after closing the app. I am using firebase otp authentication as a mode of login. I am struck here to use the previously used phone number and otp. Below is my code.
This is one screen where user will enter mobile number.
import React, {useState, useRef} from 'react'
import { Alert, View } from 'react-native';
import { NativeBaseProvider, Text, Image, Button, Input } from 'native-base';
import { Pressable } from 'react-native';
import { Col, Row, Grid } from "react-native-easy-grid";
import { LinearGradient } from 'expo-linear-gradient';
import styles from '../styles/styles';
import firebase, {phoneAuthProvider} from '../firebase';
import { FirebaseRecaptchaVerifierModal } from 'expo-firebase-recaptcha';
import AsyncStorage from '#react-native-async-storage/async-storage';
const DummyWelcome = ({ navigation }) => {
const [phoneNumber, setPhoneNumber] = useState("");
const [verificationId, setVerificationId] = useState(null);
const recaptchaVerifier = useRef(null);
const sendVerification = async () => {
try {
await AsyncStorage.setItem('phoneNumber', phoneNumber)
}
catch (erorr) {
console.log(error);
}
console.log('Storing phone Number') ;
phoneAuthProvider
.verifyPhoneNumber(phoneNumber, recaptchaVerifier.current)
.then((id) => {
// console.log('verification:',id);
setVerificationId(id);
navigation.navigate("DumOtp", {verificationId: id})
});
};
return (
<NativeBaseProvider>
<FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={firebase.app().options} />
<Grid >
<LinearGradient
colors={['#64B278', '#03621B']}
style={styles.linearStyle}/>
<Row size={40}
style={styles.containerRow}>
<Image
source={{uri: 'https://d2j6dbq0eux0bg.cloudfront.net/images/30049435/1646525107.jpg'}}
alt="Subhiksha Logo"
width= {150}
height={150}/>
</Row>
<Row size={5}
style={styles.textStyle}>
<Text
style={styles.welcomeText}>Welcome</Text>
</Row>
<Row size={5}
style={styles.textStyle}>
<View>
<Text style={styles.phoneText}>Enter your phone number to contine</Text>
</View>
</Row>
<Row size={10}
style={styles.justifyCenter}>
<Input
style={styles.inputText}
placeholder="Enter your phone Number"
placeholderTextColor= "white"
onChangeText={text => setPhoneNumber(text)}
maxLength={13}
keyboardType='phone-pad'/>
</Row>
<Row size={20}
style={styles.justifyCenter}>
<Pressable
style={styles.pressableStyle}
onPress={sendVerification}>
{/* onPress = {() => */}
{/* text.length < 10 ? Alert.alert("Invalid Submission", "Please Enter 10 digit Mobile Number to continue") : navigation.navigate("DumOtp")}> */}
<Text
style={styles.pressableTextStyle}>Generate OTP</Text>
</Pressable>
</Row>
</Grid>
</NativeBaseProvider>
)
}
export default DummyWelcome
This is another screen where otp will be auto captured.
import React,{ useState, useEffect, useRef } from 'react'
import { NativeBaseProvider, Image, View, Pressable, Text, Button } from 'native-base'
import { Col, Row, Grid } from "react-native-easy-grid";
import { LinearGradient } from 'expo-linear-gradient';
import OTPInputView from '#twotalltotems/react-native-otp-input'
import Clipboard from '#react-native-community/clipboard'
import styles from '../styles/styles';
import AsyncStorage from '#react-native-async-storage/async-storage';
import firebase from '../firebase';
import { FirebaseRecaptchaVerifierModal } from 'expo-firebase-recaptcha';
const DummyOtp = ({ navigation, route }) => {
const [seconds, setSeconds] = useState(60);
const [code, setCode] = useState('');
// const [verificationId, setVerificationId] = useState(null);
const recaptchaVerifier = useRef(null);
const {verificationId} = route.params;
// console.log(code)
useEffect(() => {
if (seconds > 0) {
setTimeout(() => setSeconds(seconds - 1), 1000);
} else {
setSeconds('OTP Expired!');
}
});
const confirmCode = async () => {
try {
const dataa = await AsyncStorage.getItem('phoneNumber');
if(dataa!== null){
const credential = firebase.auth.PhoneAuthProvider.credential(
verificationId,
code
);
firebase
.auth()
.signInWithCredential(credential)
.then((result) => {
// console.log(result);
navigation.navigate("DumQuestion1");
});
}
}
catch (error) {
console.log(error)
}
}
return (
<NativeBaseProvider>
{/* <FirebaseRecaptchaVerifierModal
ref={recaptchaVerifier}
firebaseConfig={firebase.app().options}/> */}
<Grid >
<LinearGradient
colors={['#64B278', '#03621B']}
style={styles.linearStyle}
/>
<Row size={30}
style={styles.justifyCenter}>
<Image
source={{uri: 'https://d2j6dbq0eux0bg.cloudfront.net/images/30049435/1646525107.jpg'}}
alt="Subhiksha Logo"
width= {150}
height={150}
/>
</Row>
<Row size={5}
style={styles.textStyle}>
<Text
style={styles.welcomeText}>Welcome</Text>
</Row>
<Row size={5}
style={styles.textStyle}>
<View>
<Text style={styles.phoneText}>Enter one time password to contine</Text>
</View>
</Row>
<Row size={10}
style={styles.otpRow}>
<OTPInputView
style={styles.otpStyles}
pinCount={6}
autoFocusOnLoad
codeInputFieldStyle={styles.codeInputFieldStyle}
codeInputHighlightStyle={styles.codeInputHighlightStyle}
onChangeText={text => setCode(text)}
onCodeFilled = {(code => {
setCode(code);
})}
/>
</Row>
<Row size={10}
style={styles.centerContainer}>
<Text style={styles.otpTimerText}>{seconds}</Text>
</Row>
<Row size={10}
style={styles.centerContainer}>
<Text underline style={styles.otpNotRecieved}>Didn't receive OTP?</Text>
<Text style={styles.resendText}> Resend</Text>
</Row>
<Row size={15}
style={{alignItems: 'flex-start', justifyContent: 'center', marginTop: 10}}>
<Pressable
style={styles.pressableStyle}
onPress={confirmCode}>
<Text
style={styles.pressableTextStyle}>Authenticate</Text>
</Pressable>
</Row>
{/* <Row size={15}
style={{alignItems: 'flex-start', justifyContent: 'center', marginTop: 10}}>
<Pressable
style={styles.pressableStyle}
onPress={() => console.log(verificationId)}>
<Text
style={styles.pressableTextStyle}>Login</Text>
</Pressable>
</Row> */}
</Grid>
</NativeBaseProvider>
)
}
export default DummyOtp;
So I want to use TouchableOpacity in order to press on the component and delete data from the Firebase, but instead it's deletes everything in my firebase if I do
OnPress= {this.DeleteAds(item.key)}
I tried follow instructions in here TouchableOpacity execute without touching but now the button doesn't do anything.
Here is the code :
export default class Ads extends Component {
constructor(props){
super(props);
this.state={
adlist:[],
} }
DeleteAds = (key)=>{
firebase.database().ref('/ads/'+key).remove();
navigation.navigate("Home")
console.log(key)
};
componentDidMount(){
firebase.database().ref('/ads').on('value', (snapshot) =>{
var list = []
snapshot.forEach((child)=>{
list.push({
key:child.key,
title:child.val().title,
details: child.val().details
})
})
this.setState({adlist:list})
})
}
render(){
return(
<View style={styles.container}>
<View style={styles.container_3}>
<Text> Ads</Text>
</View>
<FlatList
data={this.state.adlist}
keyExtractor={(item)=>item.key}
renderItem={({item})=>{
return(
<TouchableOpacity OnPress ={()=>this.DeleteAds(item.key)}>
<View style={styles.container_2}>
<Text style={styles.text_style1}>{item.title}</Text>
<Text>{item.details}</Text>
</View>
</TouchableOpacity>
)}}/>
</View>
)}
}
I will be grateful if you help to fix the issue.
I'm working in the react-native android app which connects WordPress woocommerce API and gets data from WordPress and process it. Everything working fine, but I'm a newbie to react-native and can't trigger out how to add a product in the cart. Also, need to show the product in cart page Below I added my code. I hope will get help.
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Platform,
StatusBar,
Image,
TouchableHighlight, ToolbarAndroid,
FlatList,
ScrollView,TextInput,
AsyncStorage
} from "react-native";
import HTMLView from 'react-native-htmlview';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { StackNavigator } from "react-navigation";
import {Icon, Button, Container, Header, Content,Left ,Right,Item,Input,Card,CardItem} from 'native-base'
import { Ionicons,FontAwesome } from '#expo/vector-icons'
import FAIcon from 'react-native-vector-icons/FontAwesome'
import * as CartAction from '../Actions/CartActions';
//Constant declaration
export const GET_PRODUCTS_SUCCESS = 'GET_PRODUCTS_SUCCESS'
export const GET_PRODUCTS_FAILED = 'GET_PRODUCTS_FAILED';
export const GET_CART_SUCCESS = 'GET_CART_SUCCESS';
export const ADD_TO_CART_SUCCESS = 'ADD_TO_CART_SUCCESS';
export const REMOVE_FROM_CART_SUCCESS = 'REMOVE_FROM_CART_SUCCESS';
class Products extends Component {
constructor(props) {
super(props);
this.state = { quantity: 1 };
}
//decrease quantity working
decreaseQuantity = () => {
if(this.state.quantity <= 1) {
return;
} else {
this.setState({
quantity: this.state.quantity - 1
});
}
}
//increase quantity working
increaseQuantitiy = () => {
this.setState({
quantity: this.state.quantity - 1 + 2
});
}
//add to cart NOT WORKING
addToCart(product, quantity) {
return (dispatch) => {
const cartItem = {
"id": product.id,
"image": product.images[0].src,
"name": product.name,
"quantity": quantity
}
dispatch({
type: types.ADD_TO_CART_SUCCESS,
item: cartItem
});
}
}
//Sidemenu Icon
static navigationOptions ={
drawerIcon:(
<FontAwesome name="home" size={30} color="black" />
)
}
//Render Block
render() {
const product = this.props.navigation.state.params.product;
return (
<Container>
//Product View
<ScrollView>
<Image style={styles.image} source={{ uri: product.images[0].src }} />
<View style={{ alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize:18,fontWeight:'bold'}}>{product.name}</Text>
<Text> ₹ {product.price}</Text>
</View>
<View style={{ display: 'flex', flexDirection: 'row', padding: 10, marginLeft: 20, marginBottom: 20 }}>
<View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center',marginTop:10 }}>
<TouchableOpacity style={styles.decreaseButton} onPress={this.decreaseQuantity}>
<Text> - </Text>
</TouchableOpacity>
<TextInput
style={styles.input}
onChangeText={(quantity) => this.setState({ quantity })}
value={`${this.state.quantity}`}
keyboardType="numeric"
/>
<TouchableOpacity style={styles.inceaseButton} onPress={this.increaseQuantitiy} >
<Text> + </Text>
</TouchableOpacity>
</View>
// ---------------- Adding to cart not working also need to show this product in cart page----------------
<TouchableOpacity style={styles.button} onPress={() => this.addToCart(product, this.state.quantity)} >
<Text style={{ color: '#fff' }}> ADD TO CART </Text>
</TouchableOpacity>
</View>
<HTMLView style={styles.html} value={product.description} />
</ScrollView>
</Container>
)
}
}
export default Products;