React Native Update Parent Array from Child Component - reactjs

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>

Related

React-native FlatList rendering issue

THE PROBLEM
see the screenshot of probleme
//below code is which loades the slider..you can also find the below snippet in ClassFlatListRender.js , when id of element passed through FlatList which equals to the selected Id then the audio slider should work, but if I trigger one audio file element all of the sliders are moving
{id == this.state.selectedOptionId ?
(<View style={[styles.viewBar, { flexDirection: 'row', }]}>
<View style={[styles.viewBarPlay, { width: playWidthMessage }]} />
</View)
:
<View><Text>no slider<Text></View>}
THE CODE
The structure of my code is this: I have a container component with all the logic and state,
which contains a FlatList component , which again contains a custom presentational List.
Container
Custom list component that includes the FlatList component and the renderItem method
invokes classFlatList component (presentational, stateless)
The container includes this component
<CustomList
items={this.state.data}
/>
CustomList:
export class CustomList extends Component {
render() {
const renderItem = ({ item }) => {
return (
<ClassFlatListRender
message={item.message}
id={item.id}
user={item.user}
timestamp={item.timestamp}
heights={item.heights}
url={item.url}
audioLength={item.audioLength}
type={item.type}
/>
)
}
let { items } = this.props
return (
<View style={styles.container}>
< FlatList
style={styles.container}
data={items.slice().sort((a, b) => b.timestamp - a.timestamp)}
// data={data}
renderItem={renderItem}
inverted={true}
extraData={items}
keyExtractor={(items) => `${items.timestamp}`}
/>
</View>
)
}
}
The ClassFlatListRender.js
export class ClassFlatListRender extends React.Component {
constructor() {
super();
this.state = {
update: false,
currentPositionSec: 0,
currentDurationSec: 0,
playTime: '00:00:00',
duration: '00:00:00',
id: '',
tempId: '',
selectedOptionId: '',
setId: '',
};
this.audioRecorderPlayer = new AudioRecorderPlayer();
this.audioRecorderPlayer.setSubscriptionDuration(0.09); // optional. Default is 0.1
}
onStartPlay = async (id, url) => {
console.log('onStartPlay');
//? Custom path
// const msg = await this.audioRecorderPlayer.startPlayer(this.path);
//? Default path
console.log("arvinf", url)
const msg = await this.audioRecorderPlayer.startPlayer(url);
console.log("msg", msg)
const volume = await this.audioRecorderPlayer.setVolume(1.0);
console.log(`file: ${msg}`, `volume: ${volume}`);
this.audioRecorderPlayer.addPlayBackListener((e) => {
this.setState({
currentPositionSec: e.currentPosition,
currentDurationSec: e.duration,
// playWidth: (e.currentPosition / e.duration) * (screenWidth - 300)
// playTime: this.audioRecorderPlayer.mmssss(
// Math.floor(e.currentPosition),
// ),
// duration: this.audioRecorderPlayer.mmssss(Math.floor(e.duration)),
});
});
};
onPausePlay = async () => {
await this.audioRecorderPlayer.pausePlayer();
};
renderElement = (id, audioLength) => {
if (this.state.selectedOptionId == id) {
// this.onStartPlay(url)
return (
<Fcon name={this.state.selectedOptionId == id ? 'play' : 'pasue'} size={24} color={'white'} />
)
}
if (this.state.selectedOptionId !== id || this.state.currentPositionSec == this.state.duration) {
// this.onPausePlay(url)
return (
<Fcon name={'play'} size={24} color={'white'} />
)
}
}
checkFunction = async (id, url) => {
console.log("id: before", id)
await this.setState({
selectedOptionId: id,
setId: id
})
console.log('id:after', this.state.selectedOptionId)
id == this.state.setId ? this.onStartPlay(id, url) : this.onPausePlay()
// return this.state.selectedOptionId
}
render() {
let { id, user, url, heights, message, audioLength, type } = this.props;
let playWidthMessage =
(this.state.currentPositionSec / this.state.currentDurationSec) *
(screenWidth - 300);
if (!playWidthMessage) {
playWidthMessage = 0;
}
return (
<View id={id}>
{
url.endsWith(".jpg") ?
< View key={id} style={[user == 1 ? styles.receiver : styles.sender, { paddingHorizontal: 14, paddingVertical: 8, borderRadius: heights > 50 ? 20 : 50 }]}>
<View style={{ alignItems: 'center', }}>
{console.log("address", url)}
<Image
resizeMode="contain"
// resizeMethod="scale"
style={{ width: 200, height: 200 }}
source={{ uri: url, width: 200, height: 200 }}
// source={{ uri: "https://picsum.photos/200", width: 200, height: 200 }}
// source={require("https://ibb.co/hM8BbY5")}
/>
</View>
</View> : null
}
{
url.endsWith(".mp3") ?
(
<View key={this.props.id} style={[user == 1 ? styles.receiver : styles.sender, { paddingHorizontal: 14, paddingVertical: 8, borderRadius: heights > 50 ? 20 : 50 }]}>
<View style={[styles.viewPlayer, { backgroundColor: user == 1 ? darkgrey : '#0096FF', alignSelf: 'center', borderRadius: 50, flexDirection: 'row', justifyContent: "center", alignItems: 'center' }]}>
{/* line */}
<TouchableOpacity activeOpacity={0.5} onPress={() => {
this.checkFunction(id, url)
}} style={{ borderRadius: 50, width: 36, height: 36, justifyContent: 'center', alignItems: 'center' }}>
<View>
{this.renderElement(id, url, audioLength)}
</View>
</TouchableOpacity>
<View >
<TouchableOpacity
style={[styles.viewBarWrapper, { width: screenWidth - 300 }]}
onPress={this.onStatusPress}
>
{id == this.state.setId ?
(<View style={[styles.viewBar, { flexDirection: 'row', }]}>
{/* {console.log("playWidth:", this.state.playWidth)} */}
<View style={[styles.viewBarPlay, { width: playWidthMessage }]} />
</View>
)
: <View><Text>ddd</Text></View>}
</TouchableOpacity>
</View>
<Text style={[styles.txtRecordCounter, { color: 'white' }]}>{audioLength}</Text>
</View>
</View >) : null
}
{
type == "txt" ?
// && user == 1 ?
<View key={id} >
<TouchableOpacity onPress={async () => await this.setState({ tempId: id })} style={[styles.receiver, { borderRadius: heights > 50 ? 20 : 50, backgroundColor: this.state.tempId == id ? 'pink' : 'yellow' }]}>
<Text style={styles.receiverText}>{message}</Text>
</TouchableOpacity>
</View> : null
}
</View >
)
}
}
Maintain the selected audio id in your parent component, pass it to child components using props, animate based on the condition. in ur message component

API image not being displayed in list

I know there are several questions with this issue but mine is different.
I trying to display an image in my Flatlist card that is coming from an API. However it is not showing up.
BUT...when I display this image in another part of my code (in an Autocomplete list) using the same code basically, it works. Also, when I try an url from an image on the Web, it displays inside the flatlist correctly
Here's my Flatlist code:
<FlatList
data={this.state.myGamesArray}
renderItem={({ item }) => (
<Card>
<CardItem>
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
</CardItem>
<CardItem>
<View>
<Text style={styles.usergameText}>
{item}
</Text>
</View>
</CardItem>
</Card>
)}
keyExtractor={(item,index) => index.toString()}
/>
Here is my Autocomplete code in which I use the same image bracket-thingy
<View style={styles.iconContainer} >
<TouchableOpacity onPress={() => this.setState({ query: item.name})}
style={styles.autocompleteList} >
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
<Text style={styles.gameText}>
{item.name}
</Text>
</TouchableOpacity>
</View>
I ran console.item(item.background_image) both inside the Flatlist(first snippet) and the Autocomplete list (Second snippet). The first shows 'undefined' and the second it shows all the URIs
App.js full code:
/*This is an example of AutoComplete Input/ AutoSuggestion Input*/
import React, { Component } from 'react';
//import react in our code.
import { StyleSheet, Text, TouchableOpacity, View, Image, FlatList, Alert, TouchableWithoutFeedback, Keyboard } from 'react-native';
//import all the components we are going to use.
import Autocomplete from 'react-native-autocomplete-input';
import { Button, List, Container, ListItem, Card, CardItem, Header, Item } from 'native-base';
import { Entypo } from '#expo/vector-icons'
//import Autocomplete component
//const API = 'https://api.rawg.io/api/games?page=1';
//Demo base API to get the data for the Autocomplete suggestion
class App extends Component {
constructor(props) {
super(props);
//Initialization of state
//films will contain the array of suggestion
//query will have the input from the autocomplete input
this.state = {
myGamesArray: [],
games: [],
query: ' ',
};
}
componentDidMount() {
//First method to be called after components mount
//fetch the data from the server for the suggestion
fetch('https://api.rawg.io/api/games?page=1&platforms=18', {
"method": "GET",
"headers": {
"x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
"x-rapidapi-key": "495a18eab9msh50938d62f12fc40p1a3b83jsnac8ffeb4469f"
}
})
.then(res => res.json())
.then(json => {
const { results: games } = json;
this.setState({ games });
//setting the data in the games state
});
}
findGame(query) {
let i;
//method called everytime when we change the value of the input
if (query === '') {
//if the query is null then return blank
return [];
}
const { games } = this.state;
//making a case insensitive regular expression to get similar value from the film json
const regex = new RegExp(`${query.trim()}`, 'i');
//return the filtered game array according the query from the input
return games.filter(game => game.name.search(regex) >= 0);
}
AddItemsToArray = () => {
var i
//verifica se input esta vazio
if (this.state.query === '') {
return Alert.alert('Voce não selecionou um jogo')
}
//VERIFY IF GAME IS IN THE ARRAY
for (i = 0; i < this.state.games.length - 1; i++) {
if (this.state.query !== this.state.games[i].name) {
if (i === this.state.games.length - 2) {
return Alert.alert('Este jogo nao existe')
}
else {
continue
}
} else {
break
}
}
//verifica repetido
if (this.state.myGamesArray.includes(this.state.query)) {
return Alert.alert('Este jogo já foi adicionado')
}
else {
//Adding Items To Array.
this.setState(prevState => {
const { myGamesArray, query } = prevState;
return {
myGamesArray: [...myGamesArray, query.toString()],
};
},
// Use setState callback to alert with the updated state
);
}
}
render() {
const { query } = this.state;
const games = this.findGame(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return (
<TouchableWithoutFeedback
onPress={() => {
Keyboard.dismiss()
}}
>
<View style={styles.container}>
<View style={styles.listContainer}
>
<FlatList
data={this.state.myGamesArray}
renderItem={({ item }) => (
console.log(item.background_image),
<Card style={{flexDirection:'row',paddingEnd:100}}>
<CardItem cardBody>
<View>
<Image
style={styles.listImage}
source={{uri: item.background_image}}
/>
</View>
</CardItem>
<CardItem>
<View>
<Text style={styles.usergameText}>
{item}
</Text>
<Text style={styles.usergameText}>
Playstation 4
</Text>
</View>
</CardItem>
</Card>
)}
keyExtractor={(item,index) => index.toString()}
/>
</View>
<View>
<Header span
style={styles.header}>
<Autocomplete
inputContainerStyle={{borderColor:'transparent'}}
style={styles.autocompleteInput}
autoCapitalize="none"
autoCorrect={false}
//data to show in suggestion
data={games.length === 1 && comp(query, games[0].name) ? [] : games}
//default value if you want to set something in input
defaultValue={query}
/*onchange of the text changing the state of the query which will trigger
the findGame method to show the suggestions*/
onChangeText={text => this.setState({ query: text })}
placeholder=" Adicione os jogos que você tem"
//This below is the 'list' of autocomplete options
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
//I GET ERROR WHEN TRYING TO ERASE (PS4) IN TEXT BOX ***NEED TO CHECK THIS
<View style={styles.iconContainer} >
<TouchableOpacity onPress={() => this.setState({ query: item.name})}
style={styles.autocompleteList} >
<View>
<Image
style={styles.gameImage}
source={{uri: item.background_image}}
/>
</View>
<Text style={styles.gameText}>
`${item.name}`
</Text>
</TouchableOpacity>
</View>
)}
/>
</Header>
</View>
<TouchableOpacity
style={styles.addButton}
onPress={() => this.AddItemsToArray()}
>
<Entypo name="plus" size={50} color="#fff" />
</TouchableOpacity>
</View>
</TouchableWithoutFeedback>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
flex: 1,
},
autocompleteInput: {
borderWidth: 1,
backgroundColor: "#fff",
borderColor: '#7843FF',
height: 50,
marginTop: 70,
borderRadius:10,
},
autocompleteList: {
flex:1,
flexDirection: 'row',
borderWidth:0.5,
borderColor: '#7843FF',
paddingVertical: 5,
paddingRight: 60,
},
listContainer: {
flex: 1,
position: 'absolute',
left: 10,
right: 10,
top:150,
flexDirection:'column',
justifyContent: 'center',
borderColor: '#7843FF',
},
gameText: {
fontSize: 15,
marginLeft: 10,
marginRight:30,
marginVertical:10,
color: '#000',
textAlign: 'left',
justifyContent: 'center'
},
usergameText: {
fontSize:15,
textAlign: 'left',
alignSelf:'stretch',
color: '#000',
},
gameImage: {
flex: 3,
height: 60,
width: 60,
marginLeft:10,
borderRadius: 100,
},
listImage: {
flex: 3,
height: 110,
width: 90,
marginLeft:0,
},
addButton: {
height:50,
width: 50,
position: 'absolute',
left: 371,
top: 71,
backgroundColor: '#7843FF',
borderTopRightRadius: 10,
borderBottomRightRadius:10,
},
usergameImage: {
height: 100,
width: 100,
borderRadius: 100,
},
header: {
backgroundColor:'#67E6DC'
}
});
export default App;

How can I update text of dynamic component on react native?

I´m new to react and react-native, I want to show a component that is composed of:
so when the user checks the corresponding checkbox I transform the mentioned component adding another view getting something like this:
The problem comes when the user clicks on the Text element because I show a modal to pick the desired hour and minutes and when this modal closes I'm pretending to update the state and this updates the Text element with the selected time but it´s not working, any advice?
this is my code:
import React from 'react';
import {View,Text, TextInput, StyleSheet,TouchableOpacity} from 'react-native';
import { CheckBox } from 'react-native-elements';
import DateTimePicker from 'react-native-modal-datetime-picker';
let frmHoras;
export default class CustomChkHorario extends React.Component{
constructor(props){
super(props);
this.state={
chk:false,
fontColor:'black',
title:'Closed',
isDateTimePickerVisible: false,
sTimeMonday:'00:00',
eTimeMonday:'00:00'
}
}
_showDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: true });
}
_hideDateTimePicker = () => this.setState({ isDateTimePickerVisible: false });
_handleDatePicked = (date) => {
console.log('A date has been picked: ', date);
this.setState({sTimeMonday:date});
this._hideDateTimePicker();
};
pressedChk = () => {
//console.log('checked:',this.state.checked);
this.setState({chk:!this.state.chk}, () =>{
if(this.state.chk==false){
this.setState({fontColor:'black', title:'Closed'});
frmHoras=null;
}else{
this.setState({fontColor:'green', title:'Open'});
frmHoras=
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
}
});
}
render(){
return(
<View style={{alignItems:'center'}}>
<View style={{flexDirection:'row',justifyContent:'center',alignItems:'center'}}>
<Text>{this.props.dia}</Text>
<CheckBox title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor='green'
textStyle={{color:this.state.fontColor}}></CheckBox>
</View>
<View>
{frmHoras}
</View>
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
const styles = StyleSheet.create({
input: {
marginHorizontal: 10,
height:25,
width:60,
borderBottomColor:'black',
borderStyle:'solid',
borderBottomWidth:1,
margin:10
}
});
_handleDatePicked = date => {
const time = new Date(date);
const timePicked = `${time.getHours()}:${time.getMinutes()}`;
this.setState({ sTimeMonday: timePicked });
this._hideDateTimePicker();
};
pressedChk = () => {
this.setState({ chk: !this.state.chk }, () => {
if (this.state.chk) {
this.setState({ fontColor: 'green', title: 'Open' });
} else {
this.setState({ fontColor: 'black', title: 'Closed' });
}
});
};
render() {
return (
<View style={{ alignItems: 'center' }}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<Text>{this.props.dia}</Text>
<CheckBox
title={this.state.title}
checked={this.state.chk}
onPress={this.pressedChk}
checkedColor="green"
textStyle={{ color: this.state.fontColor }}
/>
</View>
{this.state.chk && (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input} />
</TouchableOpacity>
</View>
)}
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._hideDateTimePicker}
mode={'time'}
/>
</View>
);
}
}
You should render frmHoras in a function, but you are currently doing that in the setState callback, which is a bit misleading in your case, as setState callback is called when setState is completed and the component is re-rendered. Look at the document which clearly mentioned about this behaviour
The second parameter to setState() is an optional callback function that will be executed once setState is completed and the component is re-rendered.
So, changes will as follows
Create a new function which will render frmHoras, let it be renderFrmHoras
renderFrmHoras = () => {
const { chk } = this.state;
if(!chk) {
return null;
}
return (
<View style={{flexDirection:'row',alignItems:'center'}}>
<Text>from:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}>{this.state.sTimeMonday}</Text>
</TouchableOpacity>
<Text>to:</Text>
<TouchableOpacity onPress={this._showDateTimePicker}>
<Text style={styles.input}></Text>
</TouchableOpacity>
</View>;
);
}
Next, update the pressedChk to set fontColor, title and chk values
pressedChk = () => {
this.setState((prevState) => {
return ({
chk: !prevState.chk,
fontColor: !prevState.chk ? 'green' : 'black',
title: !prevState.chk ? 'Open' : 'Closed'
});
})
}
Next, in the render method, just call the renderFrmHoras function
render() {
return (
...
</View>
<View>
{this.renderFrmHoras()}
</View>
<DateTimePicker
...
/>
...
);
}
Hope this will help!

TypeError: Can't read property 'map of undefined in React Native

I am doing react native project. I have array of data and in render method I am trying to looping it, Its like some custom tabbar. But, After loaded, I am trying to switching from one tab to another tab, Its throwing error and crashing like
TypeError: Can't read property 'map of undefined in React Native .
My code is
dashboard.js
constructor(props) {
super(props);
this.state = {
selectedIndex:0,
tabList:[
{tabName: ‘Telugu’, tabActiveImage:TeluguActiveImg, tabInactiveImage: TeluguInActiveImg, tabActiveText:'black', tabInactiveText: 'gray'},
{tabName: ‘Tamil’, tabActiveImage:TeluguActiveImg, tabInactiveImage: TeluguActiveImg, tabActiveText:'black', tabInactiveText: 'gray'},
{tabName: ’Hindi’, tabActiveImage: HindiActiveImg, tabInactiveImage: HindiInActiveImg, tabActiveText:'black', tabInactiveText: 'gray'},
{tabName: ‘English’, tabActiveImage: EnglishActiveImg, tabInactiveImage: EnglishInActiveImg, tabActiveText:'black', tabInactiveText: 'gray'},
]
}
}
OnTabItemHandler = (index) => {
this.setState({selectedIndex:index})
console.log('selected index is',index)
}
render(item) {
const {tabList} = this.state;
return (
<View>Some static data loading </View>
<View style = {styles.tabContainer}>
{
//loop throught the state
this.state.tabList.map((item,index)=>{
return(
//the style just to make it beautiful and easy to debug
<View style ={styles.tabInnerContainer}>
<TouchableOpacity style={styles.tabIcons}
//this onpress to handle of active selected tab
onPress={()=>this.OnTabItemHandler(index)}
>
<Image
//here's the magic show off
source={this.state.selectedIndex=index?item.tabActiveImage:item.tabInactiveImage}
style={styles.tabItemsImages}
/>
<Text style={styles.tabItemTextBlackColor}>{item.tabName}</Text>
</TouchableOpacity>
</View>
)
})
}
</View>
{this.renderBottomContent(item)}
</View>
);
}
}
and bottom view is
based on tab, I am changing the bottom view
renderBottomContent = (item) => {
this.state = { dataArray: getListData()}
switch(selectedTab) {
case "Telugu":
return <View style = {styles.flatListContainer}>
//show flat list data
}
ItemSeparatorComponent = {() => (
<View style={{height:15, backgroundColor:'blue'}/>
)}
/>
</View >
case "Tamil":
return <View style = {styles.bottomStaicScreensForTabs}>
<Text>
Tamil feature will come
</Text>
</View>
case "Hindi":
return <View style = {styles.bottomStaicScreensForTabs}>
<Text>
Hindi feature will come
</Text>
</View>
default:
return <View><Text></Text></View>
}
}
And also tab text colour not changing, always coming as black. Can
anyone help me, where I am doing wrong.
To better understand the problem I've created a snack. I'll post the code here in case it will no longer be available.
Note: it's not styled properly and images are not dynamic as you intend, but it can reproduce the question pretty well.
constructor(props) {
super(props);
this.state = {
selectedIndex: 0,
tabList: [
{
tabName: 'Telugu',
tabActiveImage: '',
tabInactiveImage: '',
tabActiveText: 'black',
tabInactiveText: 'gray',
},
{
tabName: 'Tamil',
tabActiveImage: '',
tabInactiveImage: '',
tabActiveText: 'black',
tabInactiveText: 'gray',
},
{
tabName: 'Hindi',
tabActiveImage: '',
tabInactiveImage: '',
tabActiveText: 'black',
tabInactiveText: 'gray',
},
{
tabName: 'English',
tabActiveImage: '',
tabInactiveImage: '',
tabActiveText: 'black',
tabInactiveText: 'gray',
},
],
};
}
onTabItemHandler = index => {
this.setState({ selectedIndex: index });
};
renderBottomContent = () => {
const { selectedIndex, tabList } = this.state;
const itemSelected = tabList[selectedIndex];
switch (itemSelected.tabName) {
case 'Telugu':
return (
<View style={{backgroundColor: 'yellow'}}>
<Text>Telugu feature will come</Text>
</View>
);
case 'Tamil':
return (
<View style={{backgroundColor: 'green'}}>
<Text>Tamil feature will come</Text>
</View>
);
case 'Hindi':
return (
<View style={{backgroundColor: 'cyan'}}>
<Text>Hindi feature will come</Text>
</View>
);
default:
return (
<View>
<Text>No content</Text>
</View>
);
}
};
render() {
const { tabList, selectedIndex } = this.state;
return (
<View style={styles.container}>
<Text>Some static data loading </Text>
<View style={styles.tabContainer}>
{//loop throught the state
tabList.map((item, index) => {
return (
//the style just to make it beautiful and easy to debug
<View style={styles.tabInnerContainer}>
<TouchableOpacity
style={styles.tabIcons}
//this onpress to handle of active selected tab
onPress={() => this.onTabItemHandler(index)}>
<Image
//here's the magic show off
source={
selectedIndex === index
? require('./assets/snack-icon.png')
: undefined
}
style={{ height: 30, width: 30 }}
/>
<Text
style={{
color:
selectedIndex === index
? item.tabActiveText
: item.tabInactiveText,
}}>
{item.tabName}
</Text>
</TouchableOpacity>
</View>
);
})}
</View>
{this.renderBottomContent()}
</View>
);
}
I'm still here for any clarification or improvement.
Update
Adding style like:
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
tabContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
},
});

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