passing data into a modal - react-native

I'm trying to pass some data from container to modal, and i've done this. it got error undefined is not an object evaluating (evaluating _this.props.status) is there anything i did worng? what should i call in props
these are my codes
container.js
buildPanel(index, item) {
let panel = [];
let keys = DBkeys['Requests'].MyRequest;
let status = item[keys['status']];
panel.push(<View style={{ position: 'absolute', right: 0, bottom: 0, padding: normalize(5), alignItems: 'center' }} key={'status'}>
<TouchableOpacity onPress={this.handleShowModal()}>
<Icon name={img.itemStatus[status].name} type={img.itemStatus[status].type} color={img.itemStatus[status].color} size={normalize(38)} />
</TouchableOpacity>
</View>);
return panel;
}
<View style={[styles.panelContainer, status === 'success' ? {} : { backgroundColor: color.white }]}>
<FlatList
showsVerticalScrollIndicator={false}
progressViewOffset={-10}
refreshing={this.state.refreshing}
onRefresh={this.onRefresh.bind(this)}
onMomentumScrollEnd={(event) => event.nativeEvent.contentOffset.y === 0 ? this.onRefresh() : null}
data={content}
renderItem={({ item }) => item}
keyExtractor={(item, key) => key.toString()}
/>
</View>
<IconModal visible={this.state.modalVisible} close={this.handleDismissModal} status='test' desc='test' />
IconModal.js
const IconModal = (props) => {
return(
<Modal
isVisible={props.visible}
onBackdropPress={props.close}
>
<View style={styles.dialogBox}>
<View style={styles.icon}>
<Icon></Icon>
</View>
<View style={styles.text}>
<Text style={styles.status}>{this.props.status}</Text>
<Text>{this.props.desc}</Text>
</View>
<TouchableOpacity onPress={props.close}>
<View>
<Text style={styles.buttonText}>GOT IT</Text>
</View>
</TouchableOpacity>
</View>
</Modal>
)
}
IconModal.propTypes ={
visible: PropTypes.bool.isRequired,
close: PropTypes.func,
}

Use double quotes while passing string to the component. like status="test" desc="test" instead of status='test' desc='test' . and instead of this.props.status use props.status. same with this.props.desc

Remove the this keyword. It should be just props.status and props.desc

Related

Correct way to use memo in Flatlist react native

Good evening everyone .
I have created the following Flatlist :
<View style={{ flex: 1 }}>
<FlatList
ListFooterComponent={
loadMore && page < pageMax ? (
<ActivityIndicator color={Colors.grey40} />
) : (
<View />
)
}
ListFooterComponentStyle={{ height: 200 }}
contentContainerStyle={styles.listExercise}
keyExtractor={() => uuid.v4()}
data={exercises}
renderItem={renderItemRE}
removeClippedSubviews={true}
onEndReached={() => {
setOnEndReachedCalledDuringMomentum(true);
}}
onMomentumScrollEnd={loadMoreFc}
onEndReachedThreshold={0.3}
ListEmptyComponent={
<Text contentW B18>
Nessuna Esercizio presente
</Text>
}
/>
</View>
This is renderItem function
const renderItemRE = ({ item }) => {
return (
<RenderItemRE
selectables={route.params?.selectables}
item={item}
navigation={navigation}
/>
);
};
And finally this is my component RenderItemRE
const RenderItemRE = ({ item, navigation, selectables }) => {
return (
<View style={styles.globalContainer}>
<TouchableOpacity
style={styles.touchable}
onPress={() => {
navigation.navigate(Routes.InfoEsercizio, {
id_ex: item.id,
nomeEx: item.nome,
});
}}
>
<View style={styles.container}>
<Image
indicator={Progress}
style={styles.img}
source={{
uri: item.galleria
? item.galleria[0]
? item.galleria[0]
: "logo"
: ApiConstants.DEFAULT_IMAGE,
}}
/>
<Text
style={[
customtext(DYNAMIC_FONTS_SIZE.FONT_SIZE_BIG).regular,
styles.nameStyle,
]}
>
{item.nome}
</Text>
</View>
</TouchableOpacity>
</View>
);
};
function arePropsEqual(prevProps, nextProps) {
return nextProps.item.id === prevProps.item.id;
}
export default memo(RenderItemRE, arePropsEqual);
This is a correct way to use memo in react native ? Or am I doing something wrong? I'm noticing that when the list gets bigger the rendering slows down. I was wondering what was the correct way to optimize. Thank you in advance

React native button within Card affects all other buttons in separate cards due to constant rendering

I am rendering separate cards in my render function by using data from an array. However I want a button within each Card to be pressed and only affect that exact Card.
this.state = {
isLiked: false,
feed: [{
username: ["stuff","here"],
caption: ["more","stuff"]
}]
}
toggleLike = () => {
this.setState({
isLiked = !this.state.isLiked
})
}
renderFeed = () => {
return this.state.feed.map((card, index) => {
return card.username.map((username, i) => {
if(card.caption[i])
return (
<View>
<TouchableHighlight
onPress={()=>this.toggleModal({caption:card.caption[i],username:card.username[i]})}
underlayColor="white">
<Card
key={`${i}_${index}`}
containerStyle={{borderRadius:10, marginRight:1, marginLeft:1,}}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ flexDirection: 'row'}}>
</View>
<View style={{flexDirection:'row'}}>
{this.state.isLiked ?(
<Avatar rounded icon={{name: 'heart-multiple-outline', type: 'material-community'}} overlayContainerStyle={{backgroundColor: '#ff4284',marginLeft: 5}} reverse size="small" onPress={()=> this.toggleLike()}/>
) : (
<Avatar
rounded
icon={{ name:'heart-multiple-outline', type:'material-community', color: '#ff4284'}}
overlayContainerStyle={{marginLeft:5}}
reverse
size='small'
onPress={()=> this.toggleLike()}/>
)}
</View>
</View>
<View style={{flexDirection:'row'}}>
<Text style={{fontFamily: 'MontserratB', color:'#bf00b9', marginTop:10}} key={username}>{username}</Text>
<Text style={{fontFamily:'Montserrat', marginTop:10}} key={card.caption}>{card.caption[i]}</Text>
</Card>
</TouchableHighlight>
</View>
);
return <React.Fragment />;
});
})
}
render(){
{this.renderFeed()}
}
Is there any way I can make it so that each card's like button is independent?
Here is an expo snack so you can see what I mean. https://snack.expo.io/#sooper_fly/demoforlikes
I build expo snack, Something like this:
https://snack.expo.io/#djalik/demoforlikes
you can improve your code and make card/item component and set the data over props.
Recommend: Work with FlatList

How to change views based on condition

I am new to react native development. In my application I need to change the color of the view based on the condition. So my question is can I use if condition between the views in react native. The following is the code
import React, {Component} from 'react';
import {StyleSheet, FlatList, Text, View, Alert,Image,TouchableOpacity} from 'react-native';
export default class Myproject extends Component {
constructor(props)
{
super(props);
this.state = { FlatListItems: [
{key: 'One'},
{key: 'Two'},
{key: 'Three'},
{key: 'Four'},
{key: 'Five'},
{key: 'Six'},
{key: 'Seven'},
{key: 'Eight'},
{key: 'Nine'},
{key: 'Ten'},
{key: 'Eleven'},
{key: 'Twelve'}
]}
}
FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "100%",
marginLeft: 12,
backgroundColor: "#607D8B",
}}
/>
);
}
GetItem (item) {
Alert.alert(item);
}
render() {
return (
<View style={styles.MainContainer}>
<FlatList
data={this.state.FlatListItems}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={
({item}) =>
<View style={styles.mainItem}>
<View style={styles.itemContainer}>
<View>
<Image source={require('./resource/ic_drawer.png')} />
<Text style={styles.item} onPress={this.GetItem.bind(this, item.key)}>{item.key}</Text>
</View>
<View style={styles.balanceItem}>
<View>
<Text >Balance</Text>
<Text style={{color: '#000',fontSize: 18}}>$89.04</Text>
</View>
<View style={styles.subItem}>
<View>
<Text >Account number</Text>
<Text style={{color: '#000',fontSize: 14}}>743509-001</Text>
</View>
<View style={styles.balanceItem}>
<Text >Meter number</Text>
<Text style={{color: '#000',fontSize: 14}}>17976849</Text>
</View>
</View>
</View>
<View style={styles.balanceItem}>
<View style={styles.duenbuttonItem}>
<View>
<Text >Due Date</Text>
<Text style={{color: '#000',fontSize: 14}}>30/09/2016</Text>
</View>
</View>
<TouchableOpacity style={styles.btn} onPress={this.login}><Text style={{color: 'white',fontSize: 14}}>PAY NOW</Text></TouchableOpacity>
</View>
<Image source={require('./resource/arrow_24.png')} style={styles.arrowImage}/>
</View>
</View>
}
/>
</View>
);
}
login=()=>{
alert("testing......");
// this.props.navigation.navigate('Profile');
}
}
I want the output like the below image
I have designed everything fine. But the problem is green arrow and white arrow. I have designed these arrows too. But these arrows are displaying based on the condition.
I have tried like this but getting the following issue
if(item.key == "One"){
<View style={{borderColor: 'black',borderWidth: 6,marginBottom: -6}}/>
}else{
<View style={{borderColor: 'white',borderWidth: 6,marginBottom: -6}}/>
}
So here the problem is string comparison or any other problem.
You can do even better than returning a new view. In your case you only want to change the bg color, so you can have a ternary condition inside your style like this:
<View style={{borderColor: item.key == "One" ? "black" : "white"}}/>
UPDATE for multiple condition :
defineBgColor(key){
switch(key){
case "One":
return "black";
case "Two":
return "white";
case "Three":
return "orange";
}
}
render(){
<View style={{borderColor: this.defineBgColor(item.key)}}/>
}
An 'if' condition is a statement (doesn't have a return value).
Use ternary operator you'll have a return value.
{item.key == "One" ?
<View style={{borderColor: 'black',borderWidth: 6,marginBottom: -6}} /> :
<View style={{borderColor: 'white',borderWidth: 6,marginBottom: -6}} /> }
This may work.
{item.key == "One" ?
<View style={{borderColor: 'black',borderWidth: 6,marginBottom: -6}} /> :
<View style={{borderColor: 'white',borderWidth: 6,marginBottom: -6}} />}
However, if the only thing that differs is the borderColour, you could use something like
<View style={item.key == "One" ? styles.blackborder : styles.whiteborder} />
with blackborder and white border defined
blackborder {
...
}
whiteborder {
...
}
const getBorderColor = key => {
const searchKey = key.toLowerCase();
const borderMap = {
one: 'green',
two: 'red',
three: 'white',
};
return borderMap[searchKey];
};
<FlatList
data={this.state.FlatListItems}
renderItem={({item}) => <View style={{borderColor: this.getBorderColor(item.key)}} />}
/>

How to reload Flatlist react native?

I have a rendered list and I would like it when a change in status is generated the entire FlatList is recharged
what I have is a search engine and I want that when it brings the new data the FlatList will refresh itself with the new information
I need that every time you enter a letter in the search engine the FlatList will recharge
async buscar(buscar) {
this.setState({refreshing: true});
const coins = await ajax.searchProd(buscar);
this.setState({coins});
console.log(coins);
this.setState({refreshing: false});
}
render() {
return (
<View style={styles.container}>
<Image style={styles.logoHeader} source={require('../../public/images/productos.png')}/>
<View style={styles.containerSearch}>
<TextInput
style={styles.inputBuscar}
placeholder={'Buscar Productos'}
underlineColorAndroid={"transparent"}
onChangeText={(buscar) => {
this.setState({buscar: buscar});
this.buscar(this.state.buscar);
console.log(this.state.buscar);
}}
/>
<Image style={styles.imageSearch} source={require('../../public/images/search.png')}/>
</View>
<View style={styles.containerPro}>
<FlatList
extraData={this.state.coins}
data={this.state.coins}
keyExtractor={(item) => item.id.toString()}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
}
renderItem={({item}) => {
let url = 'http://laeconomiadelsur.com/upload/' + item.foto;
const tableData = [
[<View>
<Image source={{uri: url}} style={{
width: 50,
height: 70,
}}/>
</View>,
],
[<View style={styles.cellIcons}>
<Text
style={styles.textCells}>{item.nombre}</Text>
<Text
style={styles.textCellsDescription}>{item.descripcion}</Text>
<Text
style={styles.textCellsPrecio}>{numeral(item.precio).format('$0,0')}</Text>
</View>,
],
[<View>
<Text style={styles.cantidad1}>seleccionar: </Text>
<View>
<NumericInput
onChange={(value) => {
let total = value * item.precio;
console.log(value);
console.log(total)
}}
totalWidth={calcSize(250)}
totalHeight={calcSize(70)}
minValue={0}
iconSize={15}
step={1}
sepratorWidth={0}
borderColor={'transparent'}
inputStyle={{
backgroundColor: 'rgb(252,226,227)',
borderTopColor: 'rgb(226,0,30)',
borderBottomColor: 'rgb(226,0,30)',
borderWidth: 1,
fontFamily: "NeutraText-BookSC",
fontSize: 17
}}
containerStyle={{
borderWidth: 1,
borderColor: 'rgb(226,0,30)',
backgroundColor: 'transparent',
}}
rounded
textColor='#000000'
rightButtonBackgroundColor={'rgb(235,209,210)'}
leftButtonBackgroundColor={'rgb(235,209,210)'}
/>
</View>
<Text style={styles.cantidad}>cantidad</Text>
</View>,]
];
return (
<View style={{flex: 1}} key={item.id}>
<Table style={styles.table} borderStyle={{borderWidth: 2, borderColor: 'white'}}
key={item.id}>
<Cols data={tableData} flexArr={[1, 2, 2]} style={styles.cells}
key={item.id}/>
</Table>
</View>
);
}}
/>
</View>
</View>
);
<TextInput
style={styles.inputBuscar}
placeholder={'Buscar Productos'}
underlineColorAndroid={"transparent"}
onChangeText={(buscar) => {
/* Updated buscar value won't be available in next line instantly
* just after the setState. So, better set buscar State in
* this.buscar() Function.
*/
/* this.setState({buscar: buscar}); Move to buscar Function*/
this.buscar(buscar).then(()=>{
console.log(this.state.buscar);
}).catch((e)=> console.log("Error: ",e))
}}
/>
An Async function always returns a promise object. So, while calling buscar function you should handle the promise.
async buscar(buscar) {
this.setState({
refreshing: true,
buscar: buscar,
});
const coins = await ajax.searchProd(buscar);
console.log(coins);
this.setState({
coins: conins,
refreshing: false
});
}
In Flatlist ExtraData property should contain the this.state
extraData={this.state}

React Native TouchableHighlight not working with Sectionlist

I've got a SectionList, and for every row in the list I want to be able to detect a click event.
renderList() {
if (this.state.searching) {
return (
<SectionList
sections={this.state.data}
renderSectionHeader={this.props.renderSectionHeader}
renderItem={this.props.renderItem}
/>
);
}
return null;
}
render() {
return (
<View style={styles.container}>
<Animated.View
style={{ opacity: 1 - this.state.backgroundColor }}
pointerEvents={this.state.searching ? 'none' : undefined}
>
{this.props.children}
</Animated.View>
<Animated.View
style={[
styles.backgroundColorView,
{ opacity: this.state.backgroundColor },
]}
/>
<Animated.View
style={[styles.searchResults, { top: this.state.yPos }]}
>
<TextInput
ref={(input) => { this.searchBar = input; }}
style={styles.textInput}
value={this.props.query}
onChangeText={this.onChangeText}
maxLength={100}
placeholder={this.props.placeholder}
onFocus={this.onFocus}
onBlur={this.onUnSearch}
/>
{this.renderList()}
</Animated.View>
</View>
);
For my renderItem method, I'm passing in the following PureComponent, which is just a Text contained in a TouchableHighlight.
class SubjectSearchItem extends React.PureComponent {
render() {
const item = this.props.item;
return (
<TouchableHighlight
onPress={() => console.log(item)}
>
<View style={{
marginHorizontal: 20,
marginVertical: 10,
}}
>
<Text>{`${item.item.long_name} (${item.item.short_name})`}</Text>
</View>
</TouchableHighlight>
);
}
}
and here's the renderItem prop I'm passing in
const renderItem = item => (
<SubjectSearchItem
item={item}
/>
);
The problem is, no click events are being detected. The row isn't getting highlighted, and the onPress isn't being fired. Any ideas?
Note: seems like this has been an issue for a little while