push button key value to array - arrays

I have a TouchableOpacity with key="red" and another one with key="black" and everytime a button is pushed the value should be added to the array. I've searched the internet for about one hour to find a way of doing this and I can't find nothing
import React from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
var RedBlackArray = [ "Red", "Black", "Red"];
export default class App extends React.Component {
constructor() {
super();
this.state = {
countRed: 0,
countBlack: 0
};
}
handlePressRed = () => {
this.setState(prevState => ({ countRed: prevState.countRed + 1 }));
}
handlePressBlack = () => {
this.setState(prevState => ({ countBlack: prevState.countBlack + 1 }));
}
render() {
return (
<View>
<View style={styles.container}>
<View style={styles.col1}>
<Text>red: {this.state.countRed}</Text>
<TouchableOpacity key='red' onPress={this.handlePressRed}>
<Text style={styles.button}>red!</Text>
</TouchableOpacity>
</View>
<View style={styles.col2}>
<Text>black: {this.state.countBlack}</Text>
<TouchableOpacity key='black' onPress={this.handlePressBlack}>
<Text style={styles.button.buton2}>black!</Text>
</TouchableOpacity>
</View>
</View>
<View style={{marginTop: 30, paddingLeft: 20, paddingRight:20}}>
<Text>So far the order has been:</Text>
{RedBlackArray.map((item, key)=> (
<Text key={key}>{item}</Text>
))}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
marginTop: 50,
backgroundColor: 'red',
borderColor: 'white',
borderWidth: 1,
borderRadius: 12,
color: 'white',
fontSize: 20,
fontWeight: 'bold',
overflow: 'hidden',
padding: 12,
textAlign:'center',
buton2: {
marginTop: 50,
backgroundColor: 'black',
borderColor: 'white',
borderWidth: 1,
borderRadius: 12,
color: 'white',
fontSize: 20,
fontWeight: 'bold',
overflow: 'hidden',
padding: 12,
textAlign:'center'
}
},
container: {
flexDirection: 'row',
justifyContent: 'center'
},
col1: {
paddingTop: 50,
paddingRight: 30,
justifyContent: 'center'
},
col2: {
paddingTop: 50,
paddingLeft: 30,
justifyContent: 'center'
}
});
The result would be that when Red or Black buttons are pushed, the key should be added to the array so it would be displayed in the lower part of the code but I can't find the way of doing it. Here is the full code. Also, any other advice about what I'm doing wrong is welcomed. I've just started learning React. Thank you all!

You should read basic documentation of react-native the key prop in TouchableOpacity is work as id not for key value like array. Try following code
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
red: 0,
black: 0,
};
}
onClick = (name) => {
let selected = this.state[name];
selected++;
this.setState({ [name]: selected });
};
renderButton = (name) => {
return (
<TouchableOpacity onPress={this.onClick.bind(this, name)}>
<Text>{name}</Text>
</TouchableOpacity>
);
};
render() {
const { red, black } = this.state;
return (
<View>
{this.renderButton('red')}
{this.renderButton('black')}
{red.map(() => (
<Text>red</Text>
))}
{black.map(() => (
<Text>black</Text>
))}
</View>
);
}
}

Maybe you could try to pass the desired value to the function called onPress to add it to the desired array.
handlePressBlack(passedValue) {
this.setState(prevState => ({ countBlack: prevState.countBlack + 1 });
this.setState(RedBlackArray: this.RedBlackArray.concat(passedValue));
}
<TouchableOpacity key='black' onPress={() => this.handlePressBlack('Black')}>
<Text style={styles.button.buton2}>black!</Text>
</TouchableOpacity>

Related

React Native how to create a delete button that deletes a different element as well as itself

Look at my code below please I am trying to find a way to make a delete button but i am very new to react native, i have been trying to do it for the past few hours.
import React, { useState } from 'react';
import { StyleSheet, FlatList, Text, View, Image, TextInput, Button, Keyboard, TouchableOpacity, CheckBox } from 'react-native';
import Interactable from 'react-native-interactable';
export default function App()
const [enteredGoal, setEnteredGoal] = useState('');
const [courseGoals, setCourseGoals] = useState([]);
const goalInputHandler = (enteredText) => {
setEnteredGoal(enteredText);
};
const addGoalHandler = () => {
if (enteredGoal.length > 0) {
setCourseGoals(currentGoals => [...currentGoals, enteredGoal])
} else {
alert("You have to write something!")
}
}
return (
<View style={styles.container}>
<View style={styles.topPart}></View>
<View style={styles.navBar}>
<Image source={require('./assets/baseline_menu_black_18dp.png/')} />
<Text style={styles.heading}> Grocery List </Text>
</View>
<View style={styles.body}>
<TextInput
style={styles.textInput}
placeholder='Groceries'
maxLength={20}
onBlur={Keyboard.dismiss}
value={enteredGoal}
onChangeText={goalInputHandler}
/>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton}>
<Button title="ADD" onPress={addGoalHandler} color="#FFFFFF" style={styles.saveButtonText} />
</TouchableOpacity>
</View>
<View style={styles.container}>
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete}>X</Text>
</View>
)}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
topPart: {
height: '3%',
backgroundColor: '#5498A7',
},
navBar: {
height: '10%',
backgroundColor: '#5498A7',
elevation: 3,
paddingHorizontal: 15,
flexDirection: 'row',
alignItems: 'center',
},
body: {
backgroundColor: '#edebe9',
height: '100%',
flex: 1
},
heading: {
fontWeight: "bold",
justifyContent: 'center',
paddingLeft: '13%',
fontSize: 25,
color: '#d6d4d3'
},
textInput: {
borderColor: '#CCCCCC',
borderTopWidth: 1,
borderBottomWidth: 1,
height: 50,
fontSize: 25,
paddingLeft: 20,
paddingRight: 20
},
saveButton: {
borderWidth: 1,
borderColor: '#5498A7',
backgroundColor: '#5498A7',
padding: 15,
margin: 5,
},
saveButtonText: {
color: '#FFFFFF',
fontSize: 20,
textAlign: 'center'
},
groceryItem: {
borderWidth: 1,
borderColor: 'black',
backgroundColor: '#6A686B',
padding: 15,
margin: 5,
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between'
},
groceryItemText: {
color: '#d6d4d3',
},
groceryItemDelete: {
color: 'red',
fontWeight: 'bold',
fontSize: 20
}
});
I hope you guys can find a solution I will keep u guys updated on my progress, I am constantly looking for answers but i don't really understand how to make the delete (X) work and to make it delete a different element, if you know a way to make work better just let me know i would appreciate it a lot
You have to send index to delete function.
renderItem={(itemData,index) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete.bind(index)}>X</Text>
</View>
and example delete function :
groceryItemDelete(index){
setCourseGoals(currentGoals.splice(index,1))
}
You need to implement the delete method and add an onPress event:
renderItem={(itemData, idx) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete} onPress={() => deleteItem(idx)}>X</Text>
</View>
)}
const deleteItem = idx => {
const clonedGoals = [...courseGoals]
clonedGoals.splice(idx, 1)
setCourseGoals(clonedGoals)
}

How to select only one item from a flatlist in React and change it's style?

I'm stuck with trying to make a flatlist work with one selection and change only it's background. I already got the id from the pressed item and I'm passing the information to another page. But after clicking, it's style is not changing. I need to select just one and if I click on another it should deselect the first one and keep the new one selected.
My code is as folows:
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, FlatList, Linking, ActivityIndicator } from 'react-native';
import { Searchbar } from 'react-native-paper';
export default class Merchants extends Component {
constructor() {
super()
this.state = {
search: '',
loading: false,
merchantObj: [],
btnDisabled: true,
itemId: null,
imgLink: null,
listClicked: false,
}
this.arrayholder = [];
}
componentDidMount() {
const merchantUrl = 'http://165.227.43.115:8080/merchant/merchant'
fetch(merchantUrl)
.then(response => response.json())
.then(data => {
this.setState({ merchantObj: data, loading: false },
function () {
this.arrayholder = data;
})
})
.catch(error => {
console.log(error)
});
}
search = text => {
console.log(text);
};
clear = () => {
this.search.clear();
};
SearchFilterFunction(text) {
//passing the inserted text in textinput
const newData = this.arrayholder.filter(function (item) {
//applying filter for the inserted text in search bar
const itemData = item.name ? item.name.toUpperCase() : ''.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
//setting the filtered newData on datasource
//After setting the data it will automatically re-render the view
merchantObj: newData,
search: text,
});
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "95%",
justifyContent: 'center',
backgroundColor: "#DCDCDC",
}}
/>
);
}
MerchSelected = (selectedId) => {
if (this.state.btnDisabled === true) {
return (
<View style={styles.btnDsb}>
<Text style={styles.txtBtn}>Select</Text>
</View>
)
} else {
return (
<TouchableOpacity onPress={(item) => this.props.navigation.navigate('Main', { itemId: this.state.itemId, itemImg: this.state.imgLink })}>
<View style={styles.btnSelect}>
<Text style={styles.txtBtn}>Select</Text>
</View>
</TouchableOpacity>
)
}
}
PressedItem = (itemId, itemImg) => {
console.log(itemId)
this.setState({ itemId: itemId, btnDisabled: false, imgLink: itemImg })
}
renderItem = ({ item }) => {
return (
<TouchableOpacity onPress={() => this.PressedItem(item.id, item.image)} >
<View style={styles.listItem} >
<Image
style={{ width: 80, height: 80 }}
source={{ uri: `${item.image}` }} />
<View style={{ flexDirection: 'column', marginLeft: 2 }}>
< Text style={{ fontWeight: 'bold', fontSize: 20 }} > {item.name} </Text>
{item.shoppingOption == 'STORE' ? <Text>Store</Text> : <Text>In-Store & Online</Text>}
<Text>${item.minAmount} - ${item.maxAmount}</Text>
<Text style={{ color: '#00CED1' }}
onPress={() => Linking.openURL(`${item.website}`)}>
view website
</Text>
</View>
</View>
</TouchableOpacity>
)
}
render() {
if (this.state.loading) {
return (
<View>
<Text>Loading...</Text>
</View>
);
}
return (
<View style={styles.container} >
<View style={styles.searchBar}>
<Searchbar
round
placeholder="Search"
onChangeText={text => this.SearchFilterFunction(text)}
onClear={text => this.SearchFilterFunction('')}
value={this.state.search}
/>
</View>
<View style={styles.merchantsList}>
<FlatList
data={this.state.merchantObj}
renderItem={this.renderItem}
ItemSeparatorComponent={this.FlatListItemSeparator}
keyExtractor={item => item.id.toString()}
extraData={this.state}
>
</FlatList>
</View>
<View style={styles.footerBtn}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Main', { itemId: undefined })}>
<View style={styles.btnSelect}>
<Text style={styles.txtBtn}>Cancel</Text>
</View>
</TouchableOpacity>
{this.state.btnDisabled === true ? this.MerchSelected('Sim') : this.MerchSelected('Nao')}
</View>
</View >
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f2f2f4',
alignItems: 'center',
},
searchBar: {
flex: 1,
top: '5%',
width: '90%',
backgroundColor: 'rgba(242, 242, 244,0.5)'
},
merchantsList: {
flex: 6,
width: '95%',
},
footerBtn: {
flex: 1,
width: '100%',
},
listItem: {
flexDirection: 'row',
marginTop: 5,
},
notSelected: {
backgroundColor: '#f2f2f4'
},
listItemSlc: {
backgroundColor: '#48D1CC',
},
btnSelect: {
justifyContent: 'center',
width: '95%',
borderRadius: 5,
borderColor: '#00CED1',
borderStyle: 'solid',
borderWidth: 2,
height: 40,
marginTop: 5,
marginLeft: 8,
},
btnDsb: {
justifyContent: 'center',
width: '95%',
borderRadius: 5,
backgroundColor: 'gray',
height: 40,
marginTop: 5,
marginLeft: 8,
},
txtBtn: {
textAlign: 'center',
color: '#00CED1',
fontSize: 20,
},
})
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, FlatList, Linking, ActivityIndicator } from 'react-native';
import { Searchbar } from 'react-native-paper';
export default class Merchants extends Component {
constructor() {
super()
this.state = {
search: '',
loading: false,
merchantObj: [],
btnDisabled: true,
itemId: null,
imgLink: null,
listClicked: false,
itemindex:"",
}
this.arrayholder = [];
}
componentDidMount() {
const merchantUrl = 'http://165.227.43.115:8080/merchant/merchant'
fetch(merchantUrl)
.then(response => response.json())
.then(data => {
//var l_Data = [];
//for (var l_index = 0; l_index < data.length; l_index++)
//{
// l_Data[l_index] = {
// }
//}
this.setState({ merchantObj: data, loading: false },
function () {
this.arrayholder = data;
})
})
.catch(error => {
console.log(error)
});
}
search = text => {
console.log(text);
};
clear = () => {
this.search.clear();
};
SearchFilterFunction(text) {
//passing the inserted text in textinput
const newData = this.arrayholder.filter(function (item) {
//applying filter for the inserted text in search bar
const itemData = item.name ? item.name.toUpperCase() : ''.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
//setting the filtered newData on datasource
//After setting the data it will automatically re-render the view
merchantObj: newData,
search: text,
});
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "95%",
justifyContent: 'center',
backgroundColor: "#DCDCDC",
}}
/>
);
}
MerchSelected = (selectedId) => {
if (this.state.btnDisabled === true) {
return (
<View style={styles.btnDsb}>
<Text style={styles.txtBtn}>Select</Text>
</View>
)
} else {
return (
<TouchableOpacity onPress={(item) => this.props.navigation.navigate('Main', { itemId: this.state.itemId, itemImg: this.state.imgLink })}>
<View style={styles.btnSelect}>
<Text style={styles.txtBtn}>Select</Text>
</View>
</TouchableOpacity>
)
}
}
PressedItem = (itemId, itemImg) => {
console.log(itemId)
this.setState({ itemId: itemId, btnDisabled: false, imgLink: itemImg })
}
renderItem = ({ item }) => {
return (
<TouchableOpacity onPress={() => { this.PressedItem(item.id, item.image), this.setState({ itemindex: item.id }) }} >
<View style={this.state.itemindex == item.id ? styles.SelectedlistItem : styles.listItem} >
<Image
style={{ width: 80, height: 80 }}
source={{ uri: `${item.image}` }} />
<View style={{ flexDirection: 'column', marginLeft: 2 }}>
< Text style={{ fontWeight: 'bold', fontSize: 20 }} > {item.name} </Text>
{item.shoppingOption == 'STORE' ? <Text>Store</Text> : <Text>In-Store & Online</Text>}
<Text>${item.minAmount} - ${item.maxAmount}</Text>
<Text style={{ color: '#00CED1' }}
onPress={() => Linking.openURL(`${item.website}`)}>
view website
</Text>
</View>
</View>
</TouchableOpacity>
)
}
render() {
if (this.state.loading) {
return (
<View>
<Text>Loading...</Text>
</View>
);
}
return (
<View style={styles.container} >
<View style={styles.searchBar}>
<Searchbar
round
placeholder="Search"
onChangeText={text => this.SearchFilterFunction(text)}
onClear={text => this.SearchFilterFunction('')}
value={this.state.search}
/>
</View>
<View style={styles.merchantsList}>
<FlatList
data={this.state.merchantObj}
renderItem={this.renderItem}
ItemSeparatorComponent={this.FlatListItemSeparator}
keyExtractor={item => item.id.toString()}
extraData={this.state}
/>
</View>
<View style={styles.footerBtn}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Main', { itemId: undefined })}>
<View style={styles.btnSelect}>
<Text style={styles.txtBtn}>Cancel</Text>
</View>
</TouchableOpacity>
{this.state.btnDisabled === true ? this.MerchSelected('Sim') : this.MerchSelected('Nao')}
</View>
</View >
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f2f2f4',
alignItems: 'center',
},
searchBar: {
flex: 1,
top: '5%',
width: '90%',
backgroundColor: 'rgba(242, 242, 244,0.5)'
},
merchantsList: {
flex: 6,
width: '95%',
},
footerBtn: {
flex: 1,
width: '100%',
},
listItem: {
flexDirection: 'row',
marginTop: 5,
},
SelectedlistItem: {
flexDirection: 'row',
marginTop: 5,
backgroundColor:"grey",
},
btnSelect: {
justifyContent: 'center',
width: '95%',
borderRadius: 5,
borderColor: '#00CED1',
borderStyle: 'solid',
borderWidth: 2,
height: 40,
marginTop: 5,
marginLeft: 8,
},
btnDsb: {
justifyContent: 'center',
width: '95%',
borderRadius: 5,
backgroundColor: 'gray',
height: 40,
marginTop: 5,
marginLeft: 8,
},
txtBtn: {
textAlign: 'center',
color: '#00CED1',
fontSize: 20,
},
})
above is code that's you want and the screenshot is here
Since you keep track of the selected itemId, you can simply override the style of selected item as below.
<TouchableOpacity onPress={() => this.PressedItem(item.id, item.image)} >
{/* Suppeose you want to change the background color of selected item as 'red' */}
<View style={item.id !== this.state.itemId ? styles.listItem : [styles.listItem, { backgroundColor: 'red' }]}>
...
</View>
</TouchableOpacity>
But you need to add extraData property in FlatList for telling the list to re-render.
extraData={this.state.itemId}
Hope this helps you. Feel free for doubts.

how to add keys in this project

im using react o nexpo xde and when i run the project i get a warning because my list doesnt hae keys, i want to know where and how to assing them, this is my code
import React, { Component } from 'react';
import { StyleSheet, Text, View,AppRegistry,Image,ActivityIndicator, FlatList,Navigator,TouchableHighlight, } from 'react-native';
import { StackNavigator } from 'react-navigation';
class Lista extends Component {
static navigationOptions = {
title: 'Lista',
}
constructor(props) {
super(props);
this.state = {
data:[]
};
}
load = async ()=>{
try{
let resp = await fetch('https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=fd829ddc49214efb935920463668608d')
let json = await resp.json()
this.setState({data:json.articles})
} catch (err) { console.log(err) }
}
componentDidMount(){this.load()}
render() {
return (
<View style={{ flex: 1}}>
<View style={{ flex:1,backgroundColor:'gray'}}>
<FlatList
data={this.state.data}
renderItem={({item}) => (
<TouchableHighlight onPress={() => this.props.navigation.navigate('Details', {item})}>
<View style={{ height:100,margin:15,backgroundColor:'skyblue', padding: 10, flexDirection: 'row'}}>
{item.urlToImage !== null &&
<Image source={{uri:item.urlToImage}} style={{width: 90, height: 80 }}/>
}
<View style={{ flex: 1 }}>
<Text style={{ textAlign: 'center',fontWeight: 'bold', fontSize: 18, color: 'white', flex:1, margin:10}}>{item.title}</Text>
<Text style={{ textAlign: 'right',fontWeight: 'bold', fontSize: 11, color: 'white'}}>{item.publishedAt}</Text>
</View>
</View>
</TouchableHighlight>
)}
/>
</View>
</View>
);
}
}
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
const { item } = navigation.state;
return {
title: item ? item.date : 'Details Screen',
}
};
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Image source={{uri:this.props.navigation.state.params.item.urlToImage}} style={{width: 90, height: 80 }}/>
<Text>{this.props.navigation.state.params.item.title}</Text>
<Text>{this.props.navigation.state.params.item.publishedAt}</Text>
</View>
);
}
}
const RootStack = StackNavigator(
{
Lista: {
screen: Lista,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Lista',
}
);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
i know it has to be something like, key={i} bu i hae tried in some ways and it doesnt work, im just learning react by myself so im a little confused here
ty so much
In your case you need to set up key to each child of <FlatList /> component. By react native docs recomended to use keyExtractor method defined in your component.
keyExtractor = (item, index) => index
render() {
return (
<View style={{ flex: 1}}>
<View style={{ flex:1,backgroundColor:'gray'}}>
<FlatList
data={this.state.data}
keyExtractor={this.keyExtractor}
renderItem={({item}) => (
<TouchableHighlight onPress={() => this.props.navigation.navigate('Details', {item})}>
<View style={{ height:100,margin:15,backgroundColor:'skyblue', padding: 10, flexDirection: 'row'}}>
{item.urlToImage !== null &&
<Image source={{uri:item.urlToImage}} style={{width: 90, height: 80 }}/>
}
<View style={{ flex: 1 }}>
<Text style= {{ textAlign: 'center',fontWeight: 'bold', fontSize: 18, color: 'white', flex:1, margin:10}}>{item.title}</Text>
<Text style= {{ textAlign: 'right',fontWeight: 'bold', fontSize: 11, color: 'white'}}>{item.publishedAt}</Text>
</View>
</View>
</TouchableHighlight>
)}
/>
</View>
</View>
);
}
I set just index of element as key, but you can set as you wont, but make sure it is unique. But using indexes is bad practice, it is not safe.

conditionality render headerRight - React Native

I have to render headerRight conditionally in navigation options.
Right now
static navigationOptions = ({ navigation }) => ({
title: i18N.t('atmbranchpickHeader'),
headerRight: (
<TouchableHighlight
underlayColor="#E22F39"
onPress={() => {
navigation.navigate("home");
}}
>
<Image
style={{ marginRight: 20 }}
source={require('../../resources/toolbar/home_white.png')}
/>
</TouchableHighlight>
),
headerTintColor: "white",
headerStyle: {
backgroundColor: "#E22F39"
// top: 30
}
});
My Component
import React, { Component } from "react";
import {
View,
TextInput,
Text,
TouchableOpacity,
TouchableHighlight,
StyleSheet,
AsyncStorage,
BackHandler,
Image,
FlatList,
Dimensions,
TouchableWithoutFeedback
} from "react-native";
import i18n from "../../i18n/i18n.js";
import { colors } from "../../constants/colors.js";
import Storage from "../../utils/AsyncStorage.js";
class AtmBranchTypeSelect extends Component {
// Render callBack
constructor(props) {
super(props);
this.state = {
data: [
],
stBool: false,
}
}
async componentWillMount() {
BackHandler.addEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', () => this.props.navigation.goBack());
}
static navigationOptions = ({ navigation }) => ({
title: i18n.t('atmbranchpickHeader'),
headerRight: (
<TouchableHighlight onPress={() => {
navigation.navigate('home');
}}>
<Image style={{ marginRight: 20 }} source={require('../../resources/toolbar/home_white.png')} />
</TouchableHighlight>),
headerTintColor: 'white',
headerStyle: {
backgroundColor: colors.themeColor,
// top: 30
}
});
_renderList = ({ item }) => {
return (
<TouchableWithoutFeedback onPress={(event) => this._selectedItem(item.key)}>
<View style={styles.listRowContainer}>
<View style={styles.listinside1Container}>
<Image style={styles.listImage} source={item.icon} />
<View style={styles.listContainer} onPress={(event) => this._selectedItem(item.text)} >
<Text style={styles.listHeader} >{item.header}</Text>
<Text style={styles.listValue} >{item.value}</Text>
</View>
</View>
<Image style={styles.listimgArrow} source={require('../../resources/toolbar/chevron_right_grey.png')} />
</View>
</TouchableWithoutFeedback>
);
}
// Render callBack
render() {
return (
<View style={styles.mainWrapper} >
<FlatList data={this.state.data} renderItem={this._renderList} />
</View>
);
}
}
const styles = StyleSheet.create({
mainWrapper: {
flex: 1,
height: Dimensions.get('window').height,
width: Dimensions.get('window').width,
flexDirection: 'column',
justifyContent: 'flex-start'
},
listRowContainer: {
flexDirection: 'row',
marginTop: 10,
height: 80,
backgroundColor: '#FFFFFF',
justifyContent: 'space-between',
borderBottomWidth: 1,
borderColor: 'lightgray'
},
listinside1Container: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center'
},
listContainer: {
alignItems: 'flex-start',
justifyContent: 'center',
flexDirection: 'column',
backgroundColor: '#FFFFFF',
// borderBottomWidth: 1,
// borderColor: 'lightgray'
},
listHeader: {
color: 'black',
fontFamily: 'Roboto-Medium',
marginLeft: 10,
fontSize: 18,
},
listValue: {
fontFamily: 'Roboto-Regular',
marginTop: 4,
color: 'black',
marginLeft: 10,
fontSize: 14,
},
listImage: {
alignSelf: 'center',
height: 25,
width: 25,
margin: 10
},
listimgArrow: {
// flex: 1,
// flexDirection:'row',
alignSelf: 'center',
height: 25,
width: 25,
margin: 10
},
listVal: {
borderWidth: 1,
borderRadius: 10,
color: 'darkgreen',
borderColor: 'white',
backgroundColor: 'white',
fontWeight: 'bold'
},
});
export default AtmBranchTypeSelect;
From the code I have, headerRight will be displayed in all scenarios. consider I have a scenario like based on state value I have to enable/disable headerRight Button .
for example this.state.stBool? headerRight:(.....) : null
I have to render in this way.Please guide me to achieve this.
You could nest the navigation options inside the render and toggle it based on the state value. Haven't tested and not positively on performace. Hope it helps.
import React, { Component } from "react";
import {
View,
TextInput,
Text,
TouchableOpacity,
TouchableHighlight,
StyleSheet,
AsyncStorage,
BackHandler,
Image,
FlatList,
Dimensions,
TouchableWithoutFeedback
} from "react-native";
import i18n from "../../i18n/i18n.js";
import { colors } from "../../constants/colors.js";
import Storage from "../../utils/AsyncStorage.js";
class AtmBranchTypeSelect extends Component {
// Render callBack
constructor(props) {
super(props);
this.state = {
data: [],
stBool: false
};
}
async componentWillMount() {
BackHandler.addEventListener("hardwareBackPress", () =>
this.props.navigation.goBack()
);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", () =>
this.props.navigation.goBack()
);
}
_renderList = ({ item }) => {
return (
<TouchableWithoutFeedback onPress={event => this._selectedItem(item.key)}>
<View style={styles.listRowContainer}>
<View style={styles.listinside1Container}>
<Image style={styles.listImage} source={item.icon} />
<View
style={styles.listContainer}
onPress={event => this._selectedItem(item.text)}
>
<Text style={styles.listHeader}>{item.header}</Text>
<Text style={styles.listValue}>{item.value}</Text>
</View>
</View>
<Image
style={styles.listimgArrow}
source={require("../../resources/toolbar/chevron_right_grey.png")}
/>
</View>
</TouchableWithoutFeedback>
);
};
// Render callBack
render() {
const { stBool } = this.state;
const navigationOptions = ({ navigation }) => ({
title: i18n.t("atmbranchpickHeader"),
headerRight: stBool ? (
<TouchableHighlight
onPress={() => {
navigation.navigate("home");
}}
>
<Image
style={{ marginRight: 20 }}
source={require("../../resources/toolbar/home_white.png")}
/>
</TouchableHighlight>
) : null,
headerTintColor: "white",
headerStyle: {
backgroundColor: colors.themeColor
// top: 30
}
});
return (
<View style={styles.mainWrapper}>
<FlatList data={this.state.data} renderItem={this._renderList} />
</View>
);
}
}

React Native : State value is evaluated as undefined

In my Logitem component I have a Modal which is invoked upon clicking on a Text element.
This part is working fine and I am able to handle the click event successfully.
But for some reason within the event handler method deleteSelectedRecord(), the state value is returned as 'undefined' for this.state.selecteddate
I have marked the line where the evaluation happens as Line X
This is my code
import React, { Component } from 'react';
import { Text, View, Modal, DatePickerIOS, TextInput, Button } from 'react-native';
import {
deleteSelectedRecordDB
} from '../src/helper';
import { Spinner } from '../src/Spinner';
export default class Logitem extends Component {
constructor(props) {
super(props);
const { logstringdate, bmi, weight, logdate } = this.props;
}
state = {
selecteddate: '1',
selectedweight: this.props.weight,
showmodal: false,
date: new Date(86400000 * this.props.logdate),
}
async deleteSelectedRecord(){
console.log('Delete clicked');
console.log('this.state.selecteddate ==>' + this.state.selecteddate); //LINE X
const result = await deleteSelectedRecordDB(this.props.logdate);
console.log('deleteSelectedRecord after');
console.log('result ==> '+ result);
return result;
}
setModalVisible = (visible) => {
this.setState({showmodal: visible});
}
onWeightClick = () => {
this.setState({ selecteddate: this.props.logdate, showmodal: true }, () => {
console.log('Value in props==>' + this.props.logdate);
console.log('The selecteddate in the state ==> ' + this.state.selecteddate);
});
}
onDateChange(date) {
this.setState({
date: date
});
}
render() {
return (
<View style={styles.containerStyle}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.showmodal}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={{marginTop: 22}}>
<DatePickerIOS
date={this.state.date}
mode="date"
onDateChange={(date) => this.onDateChange(date)}
style={{ height: 100, width: 300 }}
/>
</View>
<View style={{ marginTop: 22, borderColor: '#ddd', borderWidth: 5 }}>
<TextInput
returnKeyType="done"
keyboardType='numeric'
style={{
height: 40,
width: 60,
borderColor: 'gray',
borderWidth: 1,
}}
onChangeText={(text) => this.setState({ selectedweight: text })}
value={this.state.selectedweight.toString()}
/>
<Text>KG</Text>
<Button
title="Delete"
onPress={this.deleteSelectedRecord}
style={{ marginTop: 200 }}
/>
</View>
</Modal>
<View style={styles.headerContentStyle}>
<Text>{this.props.logstringdate}</Text>
<Text>{this.props.bmi}</Text>
</View>
<View style={styles.thumbnailContainerStyle}>
<Text onPress={this.onWeightClick}>{this.props.weight}</Text>
</View>
</View>
);
}
};
const styles = {
containerStyle: {
borderWidth: 1,
borderRadius: 2,
borderColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop:10,
},
thumbnailContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10,
flexDirection: 'row'
},
headerContentStyle: {
flexDirection: 'column',
justifyContent: 'space-around'
},
};
This is my output
As can be seen from the console output the state value of selecteddate is not undefined.
Can someone take a look and let me know what is wrong with the code ?
Try this code in <Button> which invokes deleteSelectedRecord method:
<Button
title="Delete"
onPress={this.deleteSelectedRecord.bind(this)}
style={{ marginTop: 200 }}
/>
You need to bind deleteSelectedRecord to this somewhere in your constructor:
this.deleteSelectedRecord = this.deleteSelectedRecord.bind(this)

Resources