Here I am calling on alert function onPress on text field .
On calling that function I am trying to open alert and on confirm I am calling another function.
But it gets hang if I am calling "showAlert1()" . This function is getting called many times
I have to call showAlert() function onPress and I have to send some value in it . And on confirmation OK button on Alert box I have to upload to server.
showAlert1(code, name, version) {
console.log("data alaert abc", code, name, version);
Alert.alert(
'Confirmation',
'Are you sure you want to migrate this tariff',
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'Cancel',
},
{ text: 'Proceed', onPress: () => this.confirmTariffMigration(code, name, version) },
]
);
}
confirmTariffMigration = (code, name, version) => {
console.log("hhhhdhhdhdhdhhdd", code, name, version);
const objData = {
addofferingActionCode: '',
offeringCode: '',
offeringName: ''
}
this.props.updateTariffMigration(objData)
}
<View style={{ marginLeft: 5, marginRight: 5, marginTop: 10, backgroundColor: '#f1f1f1' }}>
{
tariffMigrationData.map((data, index) => {
return (
// <TouchableOpacity key={index} onPress={this.showAlert1(data)}>
<View style={{ marginBottom: 10, marginLeft: 5, marginRight: 5 }} key={index}>
<Card>
<CardItem header style={{ backgroundColor: '#fff', width: '100%', justifyContent: 'space-between', borderBottomColor: '#f1f1f1', borderBottomWidth: 1 }}>
<View style={{ flexDirection: 'column', justifyContent: 'space-between' }}>
<View>
<RegularText text={`${data.offering.name}`} style={{ fontWeight: 'bold' }} />
<SmallText text={` ID ${data.offering.code}`} textColor="grey" />
</View>
</View>
<View style={{
backgroundColor: 'blue',
borderRadius: 75, height: 25, paddingRight: 10, paddingLeft: 10, paddingTop: 5
}}>
<SmallText text={'Proceed'} onPress={this.showAlert1(data.offering.code, data.offering.version, data.offering.name)} textColor='white' />
</View>
</CardItem>
</Card>
</View>
)
}
}
</View>
Try to change :
<TouchableOpacity key={index} onPress={this.showAlert1(data)}>
to
<TouchableOpacity key={index} onPress={() => this.showAlert1(data)}>
And
showAlert1 (code,name,version) {
// code
}
To
showAlert1 = (code,name,version) => {
// code
}
Make Sure you have Imported "Alert" from 'react-native', not some other module.
https://i.stack.imgur.com/oMj8s.png
First of all, try changing this:
<SmallText text={'Proceed'} onPress={this.showAlert1(data.offering.code,data.offering.version,data.offering.name)} textColor='white' />
to:
<SmallText text={'Proceed'} onPress={() => this.showAlert1(data.offering.code,data.offering.version,data.offering.name)} textColor='white' />
Also try to change
showAlert1 (code,name,version) {
#code
}
to
showAlert1 = (code,name,version) => {
// code
}
as the Kishan Bharda answer addition. when we met the problem, we should know why not just correct.
as for how to pass the function to the component props, you can read the official blog, and get more details
when we want to pass params to props, here are two ways:
<TouchableOpacity key={index} onPress={() => this.showAlert1(data)}>
<TouchableOpacity key={index} onPress={this.showAlert1.bind(this,data)}>
when your do like your question
<TouchableOpacity key={index} onPress={this.showAlert1(data)}>
it is not pass the funtion, it is called not a reference.
Related
I have an image array where I am updating each value when I click on a button in react and pick an image. However the array is constantly rerendering when I only want it to when I pick an image.
Here is my code:
function OnboardingUploadPhotos() {
const [modalVisible, setModalVisible] = useState(false);
const [permissionStatus, setPermissionStatus] = useState('');
const [files, setFiles] = useState<string[]>([]);
const [fileArray, setFileArray] = useState<string[]>(['', '', '', '', '', '', '']);
const setPermissions = useCallback(val => {
setPermissionStatus(val);
}, [setPermissionStatus]);
const setIsModalVisible = useCallback(val => {
setModalVisible(val);
}, [setModalVisible]);
async function fetchAssets() {
const recentCameraRoll = await MediaLibrary.getAssetsAsync({first: 11});
setFiles(recentCameraRoll.assets.slice(1).map(file => file.uri));
}
function replaceFileState(file: string, index: number) {
let f = [...fileArray];
f[index] = file;
setFileArray(f);
}
useEffect(() => {
fetchAssets();
}, [fetchAssets]);
return (
<View>
{permissionStatus ?
<Modal style={styles.bottomModalView} isVisible={modalVisible} backdropOpacity={0}
onBackdropPress={() => setModalVisible(false)}>
<View style={styles.modal}>
<TouchableOpacity>
<Text style={{
borderBottomWidth: 1,
borderBottomColor: '#FFF',
color: '#FFF',
textDecorationLine: 'underline',
alignSelf: 'flex-end',
justifyContent: 'center',
paddingTop: 40
}}>All photos</Text>
</TouchableOpacity>
<ScrollView horizontal={true} scrollEnabled={true}
contentContainerStyle={{justifyContent: 'center', alignItems: 'center'}}>
{files.map((file, index) => {
return (
<TouchableWithoutFeedback key={index} onPress={() => replaceFileState(file, index)}>
<Image
key={file}
style={{width: 100, height: 100, marginLeft: 10, marginRight: 10, borderRadius: 4}}
source={{uri: file}}
/>
</TouchableWithoutFeedback>
);
})}
</ScrollView>
<Text style={{fontSize: 22, color: '#FFF', marginLeft: 20, marginBottom: 20}}>Your photos</Text>
</View>
</Modal> :
null
}
<Text>Upload your photos</Text>
<View style={{flexDirection: "row", flexWrap: "wrap", justifyContent: 'space-evenly'}}>
{fileArray.slice(0,6).map((image, index) => {
console.log(fileArray)
return (
image != '' ?
<Image
key={image}
style={{width: 100, height: 100, borderRadius: 100}}
source={{uri: image}}
/> :
<OnboardingPhoto key={index} setStatus={setPermissions} setModal={setIsModalVisible}/>
)
})}
</View>
</View>
);
}
It is a modal that has all the users latest images and on click of each image it replaces the empty placeholder image with the users image on the screen. However it constantly rerenders. Id say put it in a useEffect but I do not know where! Any help would be great, thanks!
I think you need to define a key property on the TouchableWithoutFeedback component.
See the guidelines here: https://reactjs.org/docs/lists-and-keys.html
Hooks are ment to be used inside Function Components, that's maybe one of the reasons.
How do I pass FlatList items to another screen that also have a FlatList?
I'm using React Navigation V5 to pass the FlatList item to the other screen. Thats working fine. I can see the text when only using ´<Text.>{details.id}</Text .>´ but not when trying to pass it to FlatList, then there is nothing.
CODE
import React, { useState } from 'react';
import {
View,
TextInput,
FlatList,
Text,
TouchableOpacity,
Linking,
Modal,
ScrollView,
} from 'react-native';
import { useTheme } from '../Data/ThemeContext';
import DataBase from '../Data/DataBase';
import Octicons from 'react-native-vector-icons/Octicons';
export default function Home({ navigation }) {
const [search, setSearch] = useState('');
const [masterDataSource, setMasterDataSource] = useState(DataBase);
const [modalVisible, setModalVisible] = useState(false);
const [details, setDetails] = useState('');
const { colors } = useTheme();
const filteredDataSource = masterDataSource.filter((item) => {
return (
item.name.includes(search) ||
(item.id && item.id.includes(search)) ||
(item.gluten && item.gluten.includes(search)) ||
(item.company && item.company.includes(search))
);
});
const itemSeparatorComponent = () => {
return (
<View
style={{
margin: 3,
}}></View>
);
};
const emptyComponent = () => {
return (
<View style={{ alignItems: 'center' }}>
<Text style={{ color: colors.text }}>Finns inte produkten med?</Text>
<View style={{ marginTop: 30 }}>
<TouchableOpacity
onPress={() => Linking.openURL('')}>
<Text
style={{
color: colors.text,
borderWidth: 1,
borderColor: colors.text,
padding: 10,
borderRadius: 5,
backgroundColor: colors.card,
}}>
KONTAKTA OSS
</Text>
</TouchableOpacity>
</View>
</View>
);
};
const renderItem = ({ item }) => {
return (
<View>
<TouchableOpacity
style={{
marginLeft: 20,
marginRight: 20,
elevation: 3,
backgroundColor: colors.card,
borderRadius: 10,
}}
onPress={() => {
setModalVisible(true);
setDetails(item);
}}>
<View style={{ margin: 10 }}>
<Text style={{ color: colors.text }}>{item.company}</Text>
<Text style={{ color: colors.text, fontWeight: '700' }}>
{item.name}
</Text>
<Text style={{ color: colors.text }}>{item.gluten}</Text>
<Text style={{ color: colors.text }}>{item.id}</Text>
</View>
</TouchableOpacity>
</View>
);
};
return (
<View style={{ flex: 1, backgroundColor: colors.background }}>
<Modal
animationType="none"
hardwareAccelerated={true}
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.8)',
}}>
<View
style={{
backgroundColor: colors.Modal,
padding: 35,
borderRadius: 10,
width: '80%',
height: '80%',
}}>
<ScrollView showsVerticalScrollIndicator={false}>
<View style={{ marginTop: 20 }}>
<Text style={{ color: colors.text }}>{details.company}</Text>
<Text
style={{ color: colors.text, marginTop: 20, fontSize: 20 }}>
{details.name}
</Text>
<Text style={{ color: colors.text, marginTop: 20 }}>
{details.gluten}
</Text>
<Text style={{ color: colors.text, marginTop: 20 }}>
Ingredienser
</Text>
<Text style={{ color: colors.text, marginTop: 2 }}>
{details.ingredients}
</Text>
<Text style={{ color: colors.text, marginTop: 30 }}>
{details.id}
</Text>
</View>
</ScrollView>
<View
style={{
borderTopWidth: 1,
borderTopColor: colors.text,
marginBottom: 10,
}}></View>
<View
style={{ flexDirection: 'row', justifyContent: 'space-evenly' }}>
<TouchableOpacity
onPress={() => {
const updated = [...masterDataSource];
updated.find(
(item) => item.id === details.id,
).selected = true;
setMasterDataSource(updated);
navigation.navigate('Inköpslista', {
items: updated.filter((item) => item.selected),
});
}}>
<Text>Lägg i Inköpslistan</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
setModalVisible(false);
}}>
<Text style={{ alignSelf: 'center', color: '#FF0000' }}>
Stäng
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: colors.Textinput,
elevation: 12,
}}>
<TextInput
style={{
flex: 1,
backgroundColor: '#fff',
borderTopLeftRadius: 5,
borderBottomLeftRadius: 5,
}}
placeholder=" SÖK PRODUKT NAMN / STRECKKOD"
placeholderTextColor="#000"
onChangeText={(text) => setSearch(text)}
value={search}
autoCapitalize="words"
/>
<Octicons
style={{
marginLeft: 1,
padding: 13,
backgroundColor: '#fff',
height: 49,
borderTopRightRadius: 5,
borderBottomRightRadius: 5,
}}
name="checklist"
size={25}
color="#000"
onPress={() =>
navigation.navigate('Inköpslista', {
items: masterDataSource.filter((item) => item.selected),
})
}
/>
</View>
<View style={{ flex: 1, marginTop: 20 }}>
<FlatList
data={filteredDataSource}
ItemSeparatorComponent={itemSeparatorComponent}
keyExtractor={(_, index) => index.toString()}
renderItem={renderItem}
initialNumToRender={4}
maxToRenderPerBatch={5}
windowSize={10}
removeClippedSubviews={true}
updateCellsBatchingPeriod={100}
showsVerticalScrollIndicator={true}
ListEmptyComponent={emptyComponent}
contentContainerStyle={{ paddingBottom: 20 }}
/>
</View>
</View>
);
}
SECOND SCREEN
import React from 'react';
import { View, Text, FlatList, Button } from 'react-native';
export default function ShoppingList({ route, navigation }) {
const RenderItem = ({ item }) => {
return (
<TouchableOpacity
style={{ marginHorizontal: 10, marginVertical: 15 }}
onPress={() => {}}>
<Text>{item.id}</Text>
<Text>{item.name}</Text>
</TouchableOpacity>
);
};
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
marginTop: 30,
}}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<FlatList
data={route.params && route.params.items}
renderItem={RenderItem}
/>
</View>
);
}
Based on your question, this is the flow that you want
User has flat list with a set of items
When an item is clicked a modal is opened
If the user wants he clicks 'Add to cart' which will add item to cart and open cart.
When cart is opened user is shown a flatlist with the selected items.
Screen 1 : Home
Here you already have a modal but you pass a single item instead of an array.
So the better way is to use the masterDataSource state that you have and add a 'selected' property to it.
So the button in the Modal would be like this
<Button
title="Add and View Cart"
onPress={() => {
const updated = [...masterDataSource];
updated.find((item) => item.id === details.id).selected = true;
setMasterDataSource(updated);
navigation.navigate('Cart', {
items: updated.filter((item) => item.selected),
});
}}
/>
Once you click the Button you would be taken to the cart page with the items array which you have selected (This will have the previous items as well).
The Cart screen will have a Flatlist to show the items that are passed via params like below. RenderItem can be the code for your item.
<FlatList
data={route.params && route.params.items}
renderItem={RenderItem}
/>
You can run the sample below
https://snack.expo.io/#guruparan/cartexample
(Modal doesnt work properly on web you can try the android version)
According to React Native Docs, the prop data on FlatList should contain an Array, like this [{...}] or this [{...},{...},{...}...]. But you are trying to pass an Object to the FlatList on the ShoppingList screen, like this {...}.
On ShoppingList Screen when you're destructuring like the following
const { details } = route.params;
You are creating an object, which looks like this {...}
So you need to convert it to an array. Use the following code snippet
const itemInfo = []
itemInfo.push(details)
Now just pass itemInfo to data prop of FlatList.
Your ShoppingList screen should look like this.
import React from 'react';
import {
View,
FlatList,
Text,
} from 'react-native';
export default function ShoppingList({ route }) {
const { details } = route.params;
const itemInfo = [];
itemInfo.push(details);
return (
<View style={{ flex: 1, backgroundColor: "white" }}>
<FlatList
data={itemInfo}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View>
<Text style={{ color: "black" }}>{item.company}</Text>
<Text style={{ color: "black" }}>{item.name}</Text>
<Text style={{ color: "black" }}>{item.gluten}</Text>
<Text style={{ color: "black" }}>{item.id}</Text>
</View>
)}
/>
</View>
);
}
I am trying to send props with navigation. I am using stack-navigation package in react-native app.
I am using this example,
How can I send props inside this button onPress={() => navigation.navigate('Details')}>
I tried to do this one but didn't work.
onPress={() => navigation.navigate('Details', name:items)}>
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title=Home
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function DetailsScreen({ navigation,name }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>{name}</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
You can Try to pass the same way,
onPress={() => {
this.props.navigation.navigate('Details', {
title: item.title,
});
}}
while receiving can use the following way,
this.props.route.params.title
I have some data in my firestore. The structure is :
User -> DocId(Some id)-> name(String), number(String), friends (array)
I got the friends array and i append to my local array data. Now when i render in the flat list. Its not showing. But same temp data which i created locally its working fine. I check my array data count after i fetch from firestore. Its showing correct count. But not able to display the data in flat list.
My code :
import firebase from '#react-native-firebase/app';
import firestore from '#react-native-firebase/firestore';
UserArray =[]
export default class HomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
UserArray: [],
}
}
componentWillMount() {
firebase.firestore().doc(`User/${'beQVEcfLsXV8JhA8L2SDDq03bmD3'}`)
.get()
.then(doc => {
this.setState({UserArray: doc.data().friends})
})
}
renderPost = post => {
return (
<View style={styles.feedItem}>
<Feather name="book" style={styles.avatar} size={30}/>
<View style={{ flex: 1 }}>
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
<View>
<Text style={styles.name}>{post.name}</Text>
<Text style={styles.timestamp}>{post.name} | {post.name}</Text>
</View>
</View>
</View>
<Feather name="chevron-right" style={{color: "#808080", alignSelf: 'center'}} size={20}/>
</View>
);
};
render() {
return (
<View style={styles.container}>
{
UserArray.length ?
(<FlatList
style={styles.feed}
data={UserArray}
keyExtractor={(index) => index.toString()}
renderItem={({ item }) => this.renderPost(item)}
// keyExtractor={item => item.id}
showsVerticalScrollIndicator={false}
></FlatList>) :
(
<View style={{ width: '70%', alignSelf: 'center',justifyContent: 'center' , alignItems: 'center', marginTop: '20%'}}>
<Feather name="smile" color="#009387" size={40}/>
<Text style={{paddingTop: 20, textAlign: 'center', fontSize: 15, fontWeight: 'bold', color: '#A9A9A9'}}>Hey folk, You dont' have any friends list</Text>
</View>
)
}
</View>
);
}
}
In my screen i am always getting. You don't have any data.
But in componentDidMount() after i fetch data from firestore. Inside my then :
.then(doc => {
alert(UserArray.length);
})
Its showing correct array count. Here is my friends array :
{
"name": "quaroe",
"number": "3940904",
friends: [
{
"name": "alber"
},
{
"name": "romea"
},
{
"name": "basea"
}
]
}
my doubt is that render is called before componentDidMount. But i tried componentWillMount. And i added alert. Always render called first and then only componentWillMount or componentDidMount is getting called
Put your UseArray in the state instead. I believe the flatlist is not showing anything because when it is rendered your firebase function is not yet completed so UseArray is empty. And render cant detect changes of your constant UseArray that why it's not showing any list even if your fetch is succesful.
try this
import firestore from '#react-native-firebase/firestore';
export default class HomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
userArray: [],
};
}
componentDidMount() {
firebase
.firestore()
.doc(`User/${'beQVEcfLsXV8JhA8L2SDDq03bmD3'}`)
.get()
.then(doc => {
this.setState({userArray: doc.data().friends});
});
}
renderPost = post => {
return (
<View style={styles.feedItem}>
<Feather name="book" style={styles.avatar} size={30} />
<View style={{flex: 1}}>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<View>
<Text style={styles.name}>{post.name}</Text>
<Text style={styles.timestamp}>
{post.name} | {post.name}
</Text>
</View>
</View>
</View>
<Feather
name="chevron-right"
style={{color: '#808080', alignSelf: 'center'}}
size={20}
/>
</View>
);
};
render() {
return (
<View style={styles.container}>
{this.state.userArray && this.state.userArray.length > 0 ? (
<FlatList
style={styles.feed}
data={this.state.userArray}
keyExtractor={index => index.toString()}
renderItem={({item}) => this.renderPost(item)}
// keyExtractor={item => item.id}
showsVerticalScrollIndicator={false}
/>
) : (
<View
style={{
width: '70%',
alignSelf: 'center',
justifyContent: 'center',
alignItems: 'center',
marginTop: '20%',
}}>
<Feather name="smile" color="#009387" size={40} />
<Text
style={{
paddingTop: 20,
textAlign: 'center',
fontSize: 15,
fontWeight: 'bold',
color: '#A9A9A9',
}}>
Hey folk, You dont' have any friends list
</Text>
</View>
)}
</View>
);
}
}
I am trying to access camera using React native app. I have copied all the code from official documentation. Every one has done the same including the official expo-docs https://docs.expo.io/versions/latest/sdk/camera/. My code to access the camera and take picture is
export default function Cameracontrol() {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(Camera.Constants.Type.back);
async function takePicture() {
console.log(this.camera)
if (this.camera) {
console.log('Pictactue Taken')
let photo = await this.camera.takePictureAsync();
}
else {
console.log('Caera Not Open');
}
}
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission === null) {
return <View />;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
return (
<View style={{ flex: 1 }}>
<Camera style={{ flex: 1 }} type={type}
ref={camera => this.camera = camera}
>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<View style={{ flex: 1, flexDirection: "row", justifyContent: "space-between", margin: 20 }}>
<TouchableOpacity
style={{
alignSelf: 'flex-end',
alignItems: 'center',
backgroundColor: 'transparent',
}}
onPress={() => {
setType(
type === Camera.Constants.Type.back
? Camera.Constants.Type.front
: Camera.Constants.Type.back
);
}}>
<Ionicons
name="ios-photos"
style={{ color: "#fff", fontSize: 40 }}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={takePicture}
style={{
alignSelf: 'flex-end',
alignItems: 'center',
backgroundColor: 'transparent',
}}>
<FontAwesome
name="camera"
style={{ color: "#fff", fontSize: 40 }}
/>
</TouchableOpacity>
<TouchableOpacity
style={{
alignSelf: 'flex-end',
alignItems: 'center',
backgroundColor: 'transparent',
}}>
<MaterialCommunityIcons
name="camera-switch"
style={{ color: "#fff", fontSize: 40 }}
/>
</TouchableOpacity>
</View>
</View>
</Camera>
</View>
);
}
I am experiencing the following error.
undefined is not an object (evaluating '_this.camera = camera')
this error is strongly related with the line
ref={camera => this.camera = camera}
By removing this line of code the error is also removing.
I would really really appreciate if some boy would help me with this.
You are in a functional component, not a class. Therefore, you cannot use this. Also, ref is not working like in classes.
You should use useRef : https://reactjs.org/docs/hooks-reference.html#useref
const inputEl=useRef(null);
<input ref={inputEl} type="text" />