Adding item to Flatlist by getParam - reactjs

DIET (MAIN PAGE)
export class Diet extends Component {
constructor(props) {
super(props);
this.state = {
foodList: [],
};
}
render() {
return (
<View style={{ flex: 1, top: hp("12%"), height: hp("100%") }}>
<Button onPress={()=> this.props.navigation.navigate('FoodCreate')}>
<Text>Press to insert Food Name</Text>
</Button>
<FlatList
data={{this.props.route?.params?.foodList}
keyExtractor={(item, index) => item.key.toString()}
renderItem={(data) => (
<ListItem itemDivider title={data.item.food} />
)}
/>
</View>
FOODCREATE
export class FoodCreate extends Component {
constructor(props) {
super(props);
this.state = {
food: null,
foodList: [],
};
}
submitFood = (food) => {
this.setState({
foodList: [
...this.state.foodList,
{
key: Math.random(),
name: food,
},
],
});
this.props.navigation.navigate("Diet", {
foodList: this.state.foodList,
});
};
render() {
return (
<Container>
<Header>
<Left>
<Button transparent>
<Icon
name="arrow-back"
onPress={() => this.props.navigation.goBack()}
style={{ fontSize: 25, color: "red" }}
/>
</Button>
</Left>
<Body>
<Title>Add Food</Title>
</Body>
<Right>
<Button transparent>
<Icon
name="checkmark"
style={{ fontSize: 25, color: "red" }}
onPress={() => {
this.submitFood(this.state.food);<-----------
}}
/>
</Button>
</Right>
</Header>
<View style={{ alignItems: "center", top: hp("3%") }}>
<TextInput
placeholder="Food Name"
placeholderTextColor="white"
style={styles.inptFood}
value={this.state.food}
onChangeText={(food) => this.setState({ food })}
/>
</View>
Hey everyone, so this is how this app should work: when I start Expo it brings me to the Diet screen, from there I press the Button to add a new food to the Flatlist, once I get sent to FoodCreate screen I type in the TextInput the name of the food and when I click the checkmark in the header it should send me back to Diet and display in the Flatlist the name of the food I typed, and so on. When I run the app it gives me the following error: this.props.navigation.getParam is not a function

You have to use
this.props.route.params.foodList
The parameters are passed via the route.params prop, with Navigation v5 the getParams option is not there

Related

React Native Update Parent Array from Child Component

I am having trouble updating an array that is passed as a prop into my child component. I have searched around but haven't found an answer that can directly solve my problem. My code is as follows:
App.js
import React, { Component } from 'react';
import { StyleSheet, Text, View, SafeAreaView } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import AddMedication from "./src/AddMedication";
import MedicationList from './src/MedicationList';
const Stack = createNativeStackNavigator();
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
medications: [],
}
this.addMedication = this.addMedication.bind(this);
}
addMedication = (name, dosage, measurement, timesDaily) => {
console.log("Medication added.")
var newItem = {name: name, dosage: dosage, measurement: measurement, timesDaily: timesDaily}
this.setState({
medications: [...this.state.medications, newItem]
})
}
render() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Medication List">
{(props) => <MedicationList {...props} medications={this.state.medications} />}
</Stack.Screen>
<Stack.Screen name="Add New Medication">
{(props) => <AddMedication {...props} addMedication={this.addMedication} />}
</Stack.Screen>
</Stack.Navigator>
</NavigationContainer>
);
}
}
This is the home screen where I am trying to display the array but nothing shows up
MedicationList.js
class MedicationList extends Component {
constructor(props) {
super(props);
this.state = {
tableHead: ['Name', 'Dosage', 'Times Daily', 'Prescriber', 'For Diagnosis'],
}
}
medication = ({ item }) => {
<View style={{ flexDirection: 'row' }}>
<View style={{ width: 50, backgroundColor: 'lightyellow'}}>
<Text style={{ fontSize: 16, fontWeight: 'bold', textAlign: 'center'}}>{item.name}</Text>
</View>
<View style={{ width: 400, backgroundColor: 'lightpink'}}>
<Text style={{ fontSize: 16, fontWeight: 'bold' , textAlign: 'center'}}>{item.dosage}{item.selectedMeasurement}</Text>
</View>
<View style={{ width: 400, backgroundColor: 'lavender'}}>
<Text style={{ fontSize: 16, fontWeight: 'bold' , textAlign: 'center'}}>{item.timesDaiy}</Text>
</View>
</View>
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', marginTop: '10%'}}>
<Button
title="+ Add New Medication"
onPress={() => {
/* 1. Navigate to the Details route with params */
this.props.navigation.navigate('Add New Medication', {
medications: this.props.medications,
});
}}
/>
<FlatList
data={this.props.medications}
renderItem={this.medication}
/>
</View>
);
}
}
This is where I click the add button to update the medications array
AddMedication.js
class AddMedication extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
dosage: 0,
selectedMeasurement: "mg",
timesDaily: '',
prescriber: '',
forDiagnoses: '',
instructions: '',
validity: false,
};
}
setName = (name) => {
let isValid = this.isFormValid();
this.setState({ name: name, validity: isValid });
}
setDosage = (dosage) => {
let isValid = this.isFormValid();
this.setState({ dosage: dosage, validity: isValid });
}
setMeasurement = (measurement) => {
this.setState({ selectedMeasurement: measurement });
}
setTimesDaily = (timesDaily) => {
let isValid = this.isFormValid();
this.setState({ timesDaily: timesDaily, validity: isValid });
}
setPrescriber = (prescriber) => {
this.setState({ prescriber: prescriber });
}
setDiagnoses = (diagnoses) => {
this.setState({ forDiagnoses: diagnoses });
}
setInstructions = (instructions) => {
this.setState({ instructions: instructions });
}
isFormValid = () => {
return (this.state.name !== '' && (this.state.dosage !== '' && this.state.dosage > 0)
&& (this.state.timesDaily !== '' && this.state.timesDaily > 0));
}
render() {
return (
<View style={styles.container}>
<Text style={{color: 'red', marginBottom: 5, marginLeft: -125}}>* denotes required field</Text>
<View style={{flexDirection: 'row'}}>
<Text style={styles.required}>*</Text>
<TextInput
style={styles.inputText}
onChangeText={(name) => this.setName(name)}
placeholder="Medication Name"
value={this.state.name}
/>
</View>
<View style={{flexDirection: 'row'}}>
<Text style={styles.required}>*</Text>
<TextInput
style={styles.inputText}
onChangeText={(dosage) => this.setDosage(dosage)}
placeholder="Dosage"
value={this.state.dosage}
/>
</View>
<View style={styles.dosageContainer}>
<Text style={{flex: 1, marginTop: 100, marginLeft: 30}}>
Select Measurement:
</Text>
<Picker
style={styles.picker}
selectedValue={this.state.selectedMeasurement}
onValueChange={(itemValue, itemIndex) =>
this.setMeasurement(itemValue)
}>
<Picker.Item label="mg" value="mg" />
<Picker.Item label="g" value="g" />
<Picker.Item label="ml" value="ml" />
</Picker>
</View>
<View style={{flexDirection: 'row'}}>
<Text style={styles.required}>*</Text>
<TextInput
style={styles.inputText}
onChangeText={(timesDaily) => this.setTimesDaily(timesDaily)}
placeholder="Times daily"
value={this.state.timesDaily}
/>
</View>
<TextInput
style={styles.inputText}
onChangeText={(prescriber) => this.setPrescriber(prescriber)}
placeholder="Prescriber"
value={this.state.prescriber}
/>
<TextInput
style={styles.inputText}
onChangeText={(diagnoses) => this.setDiagnoses(diagnoses)}
placeholder="For diagnoses"
value={this.state.forDiagnoses}
/>
<TextInput
style={styles.inputText}
onChangeText={(instructions) => this.setInstructions(instructions)}
placeholder="Instructions"
value={this.state.instructions}
/>
<TouchableOpacity
style={this.isFormValid() ? styles.validButton : styles.invalidButton}
disabled={!Boolean(this.state.name && this.state.dosage && this.state.timesDaily)}
onPress={() => {
this.props.navigation.goBack()
this.props.addMedication(this.state.name, this.state.dosage,
this.state.selectedMeasurement, this.state.timesDaily)
}}
>
<Text style={{color: 'white'}}>Add Medication</Text>
</TouchableOpacity>
</View>
)
}
}
You can pass the state value but I think you cannot pass the addMedication method just like this.
Could you please try passing an arrow function that uses the setState method?
For example:
<Stack.Screen name="Add New Medication">
{(props) => <AddMedication {...props} addMedication={(name, dosage, measurement, timesDaily)=> {this.addMedication(name, dosage, measurement, timesDaily)}} />}
</Stack.Screen>

Fetch data from realtime database firebase in react native?

I already have data in my realtime database. I can also fetch it successfully. Now what I need to do is output it in a tinder-like card view. I am currently outputting data using a 'Demo' file which exports a hard-coded array that contains sample information of some users. Using the demo array, the card output is working. But when I fetch data from firebase and store it in an array named items[], nothing is displayed on my output screen. My code is as follows:
Home Screen
import React from 'react';
import { View, ImageBackground } 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: []
});
}
componentWillMount() {
var items = [];
db.ref('cards').once('value', (snap) => {
snap.forEach((child) => {
let item = child.val();
item.id = child.key;
items.push({
pet_name: child.val().pet_name,
pet_gender: 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 });
console.log(items);
});
}
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
}}
>
{Demo.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;
Demo Data
module.exports = [
{
id: 3,
name: 'whatever',
status: 'Online',
match: '78',
description:
'Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.',
message:
'I will go back to Gotham and I will fight men Iike this but I will not become an executioner.',
image: require('./images/01.jpg')
},
{
id: 2,
name: 'Clementine Bauch',
match: '93',
description:
'Full-time Traveller. Globe Trotter. Occasional Photographer. Part time Singer/Dancer.',
status: 'Offline',
message: "Someone like you. Someone who'll rattle the cages.",
image: require('./images/02.jpg')
}
];
fetching data:
import {db} from '../config/config';
var items = [];
db.ref('cards').once('value', (snap) => {
snap.forEach((child) => {
let item = child.val();
item.id = child.key;
items.push({
pet_name: child.val().pet_name,
pet_gender: child.val().pet_gender,
pet_age: child.val().pet_age,
pet_breed: child.val().pet_breed,
photoUrl: child.val().photoUrl,
});
});
//console.log(items)
for (var i in items){
console.log(items[i])
}
});
export var items;
I want to use my items[] array instead of the Demo hard-coded array. How do I do this?
The output of items[] array:
Array [
Object {
"pet_age": "11",
"pet_breed": "golden retriever",
"pet_gender": "male",
"pet_name": "dawn",
"photoUrl": "picture",
},
Object {
"pet_age": "7",
"pet_breed": "German",
"pet_gender": "Male",
"pet_name": "Rambo",
"photoUrl": "https://firebasestorage.googleapis.com/v0/b/woofmatix-50f11.appspot.com/o/pFkdnwKltNVAhC6IQMeSapN0dOp2?alt=media&token=36087dae-f50d-4f1d-9bf6-572fdaac8481",
},
]
CardItem component:
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;

How to close a modal in react native?

I am unable to close a modal. I am displaying few images inside it, and onPress of the "X(close)" icon, want to close the modal. I have tried setting the state of modalvisible to false, by default which is set to true. But on press of icon the modal doesn't gets closed. Any solution would be of great help.
export default class imagenav extends Component{
constructor(props){
super(props)
state = {
modalVisible: false,
}
}
openmodal(){
this.setState(modalVisible: true)
}
render() {
return (
<Container>
<Modal onRequestClose={() => {}}>
<GallerySwiper
style={{ flex: 1, backgroundColor: "black" }}
images={[
{source: {uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Google_Images_2015_logo.svg/1200px-Google_Images_2015_logo.svg.png",
dimensions: {width: 1080, height: 1920}}
},
]}
/>
<Header
style={{
backgroundColor: 'black',
borderBottomWidth: 0,
}}
>
<Right>
<Icon
name='close'
color='white'
onPress={() => {
this.setState({
modalVisible: false,
})
console.log("getting closed");
}}
/>
</Right>
</Header>
</Modal>
</Container>
);
}
}
You could use an inline if to only render your modal is your state allows it :
{this.state.modalVisible &&
<Modal onRequestClose={() => { }}>
<GallerySwiper
style={{ flex: 1, backgroundColor: "black" }}
images={[
{
source: {
uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Google_Images_2015_logo.svg/1200px-Google_Images_2015_logo.svg.png",
dimensions: { width: 1080, height: 1920 }
}
},
]}
/>
<Header
style={{
backgroundColor: 'black',
borderBottomWidth: 0,
}}
>
<Right>
<Icon
name='close'
color='white'
onPress={() => {
this.setState({
modalVisible: false,
})
console.log("getting closed");
}}
/>
</Right>
</Header>
</Modal>
}
You have a state, but you are not using it
<Modal onRequestClose={()=> this.openmodal(false)} visible={this.state.modalVisible}> should be good to go.
oh and your openmodal function can be used for opening and closing the modal
openmodal(value){
this.setState({modalVisible: value})
}
<Icon
name='close'
color='white'
onPress={() => {
this.openmodal(false)
console.log("getting closed");
}}
/>
It is enough to put a state for it in visible as bellow:
<Modal onRequestClose={()=> null} visible={this.state.active} transparent={true}>
/////your Views and things to show in modal
</Modal>
in your state you have to make it as blew:
constructor(props) {
super();
this.state = {
active:false,
}
}
And then you have to toggle it in an onPress for example:
onPress=()={
this.setState({active:true})
}
So totally in your project you will have:
export default class imagenav extends Component{
constructor(props){
super(props)
state = {
modalVisible: false,
}
}
openmodal(){
this.setState({modalVisible: true})
}
render() {
return (
<Container>
<Modal visible={this.state.modalVisible} onRequestClose={() => {}}>
<View style={{flex:1}}>
<GallerySwiper
style={{ flex: 1, backgroundColor: "black" }}
images={[
{source: {uri: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Google_Images_2015_logo.svg/1200px-Google_Images_2015_logo.svg.png",
dimensions: {width: 1080, height: 1920}}
},
]}
/>
<Header
style={{
backgroundColor: 'black',
borderBottomWidth: 0,
}}
>
<Right>
<Icon
name='close'
color='white'
onPress={() => {
this.setState({
modalVisible: false,
})
console.log("getting closed");
}}
/>
</Right>
</Header>
</View>
</Modal>
</Container>
);
}
}
Update:
According to your last request there is a way. You can pass flag to your next screen and in the componentDidMount() of next screen you can check it. if it is true you can show the modal otherwise ignore it.
I hope I could help. :)

How can I display an array of images inside a Modal in react-native?

I am using galleryswiper library to display an array of images inside a modal but when i navigate to the modal component and onPress the modal opens up i don't see any images. Can anyone help me how to pass the image sources inside the modal? Also i am unable to close the modal on Press of the icon.
export default class imagenav extends Component{
constructor(props){
super(props)
state = {
modalVisible: true,
};
}
closeModal() {
this.setState({modalVisible: false});
}
render() {
return (
<Modal visible={this.modalVisible} onRequestClose={() => {} }>
<GallerySwiper
style={{ flex: 1, backgroundColor: "black" }}
images={[
{source: {uri:
dimensions: {width: 1080, height: 1920}}
}
]}
/>
<Header
style={{
backgroundColor: 'black',
borderBottomWidth: 0,
}}
>
<Right>
<Icon
name='close'
color='white'
onPress={() => {
this.setState({
modalVisible: false
})
//this.closeModal()
}}
/>
</Right>
</Header>
</Modal>
);
}
}

How to pass form data to another page in react native?

I've created a login page like this:
class Login extends Component {
render() {
const { navigate } = this.props.navigation
return (
<View style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.container1}>
<TextInput
style={{ width: 190, color: 'white' }}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
/>
<TextInput
placeholder="Password"
secureTextEntry
returnKeyType="go"
ref={input => (this.passwordInput = input)}
style={{ width: 190, color: 'white' }}
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
/>
<TouchableOpacity style={{ top: 10 }}>
<Button
color="#314561"
onPress={() => navigate('HomePage')}
title="Login"
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
export default Login
Now I need to pass the username to the home page. I've referred a number of resources and didn't got any solutions. How can I pass the username to home page?
First save your input value to some variables using onChangeText
<TextInput
value= {this.state.userName}
onChangeText = {(text)=>{
this.setState({userName:text});
}
/>
Then you can pass the value ,
<Button
onPress={() => navigate('HomePage',{"userName":this.state.userName})} // you can pass objects
title="Login"
/>
Do the following changes :
In Login component :
Username Field
<TextInput
style={{width:190,color:'white'}}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid='#f9f9f9'
onChangeText=
{(username)=>this.setState({username})}
/>
Button :
<TouchableOpacity style={{top:10}}>
<Button
color="#314561"
onPress={() => navigate('HomePage'), { username: this.state.username }}
title="Login"/>
</TouchableOpacity>
In Home component:
e.g. render method
render(){
const {state} = this.props.navigation;
console.og(state.params.username)
}
Update :
In login constructor,initialise state
constructor(){
super();
this.state = {};
}
class Login extends Component {
constructor(props) {
super(props);
this.state = {
userName:"",
password:""
};
}
updateUserName = (name) =>{
this.setState({
userName:name,
})
}
updatePwd = (pwd) =>{
this.setState({
password:pwd,
})
}
render() {
const { navigate } = this.props.navigation
return (
<View style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.container1}>
<TextInput
style={{ width: 190, color: 'white' }}
placeholder="User Name"
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
onChangeText={(name) => this.updateUserName(name)}
value={this.state.userName}
/>
<TextInput
placeholder="Password"
secureTextEntry
returnKeyType="go"
ref={input => (this.passwordInput = input)}
style={{ width: 190, color: 'white' }}
placeholderTextColor="#f9f9f9"
underlineColorAndroid="#f9f9f9"
onChangeText={(pwd) => this.updatePwd(pwd)}
value={this.state.password}
/>
<TouchableOpacity style={{ top: 10 }}>
<Button
color="#314561"
onPress={() => navigate('HomePage',{userName:this.state.userName})}
title="Login"
/>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
export default Login
file : homePage.js
constructor(props) {
super(props);
const { params } = this.props.navigation.state;
var data = params.userName;
this.state = {
userName : data
};
}

Resources