When I set State in function component I getting too many render error - react-native

UserAttemp.js
const setModal = ({ item }) => {
const perc = (item.score * 100) / item.total;
console.log("perc", perc);
if (perc >= 70) {
setImagePath(smile);
} else if (perc >= 40 && perc < 70) {
setImagePath(dis);
} else {
setImagePath(sad);
}
setTotal(item.total);
console.log("item_id",item.attempt_id);
console.log("item_total",item.total)
// setAttemp(item.attempted_question);
setScore(item.score);
setWrong(item.wrong);
setSkip(item.skip);
setModalVisible(true);
// setboolThree(false);
// setboolTwo(true);
};
const renderItem = ({ item }) => {
return (
<TouchableOpacity
style={styles.userAttemptItemContainer}
onPress={() => setModal({ item })}
>
<View>
<Text style={{alignSelf:'center',color:'black',textTransform:'uppercase'}}>{item.attempt_id}</Text>
<View
style={{ flexDirection: "row", justifyContent: "space-around" }}
>
<Text style={styles.userAttempRenderText}>Score</Text>
<Text style={styles.userAttempRenderText}>{item.score}</Text>
</View>
<Date_time
item={item}/>
</View>
</TouchableOpacity>
);
};
return (
<View>
<Loader bool={bool} />
{!bool && (
<View>
<View style={{ alignSelf: "center" }}>
<Text style={{ color: "black", fontSize: 20 }}>{title}</Text>
</View>
<FlatList
data={attempt}
renderItem={renderItem}
ListFooterComponent={<View style={{ height: 0, marginBottom: 90 }}></View>}
ListEmptyComponent={() => <EmptyListMessage />}
></FlatList>
</View>
)}
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.ResultModalCenterView}>
<View style={styles.ResultModalView}>
<View style={styles.ResultModalClosebuttonCon}>
<Pressable
style={[styles.ResultModalButton, styles.ResultButtonClose]}
onPress={() => setModalVisible(!modalVisible)}
>
<Icon name="close" size={20} color="black" />
</Pressable>
</View>
<ModalView
score={score}
total={total}
wrong={wrong}
title={title}
skip={skipp}
attempted={attempted}
imagePath={imagePath}
/>
</View>
</View>
</Modal>
</View>
);
};
export default UserAttemps;
Date_time.js
import React, { useState } from 'react'
import { View,Text } from 'react-native';
const Date_time=(props)=> {
const [dateBool,setDateBool]=useState(props.item?false:true);
const [timeBool,setTimeBool]=useState(props.item?false:true);
if(props.item.start_date==props.item.end_date){
setDateBool(true);
}
if(props.item.start_time==props.item.end_time){
setTimeBool(true);
}
return (
<View>
{dateBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Date:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_date}</Text>
</View>}
{!dateBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Date:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_date}</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.end_date}</Text>
</View>}
{/* <View style={{flexDirection:'row',justifyContent:'center'}}>
<Text style={{color:'black'}}>Date</Text>
<Text style={{color:'black'}}>{Date}</Text>
</View> */}
{ timeBool&& <View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Time:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_time}</Text>
</View>}
{timeBool&&<View style={{flexDirection:'row',justifyContent:'center',}}>
<Text style={{color:'black',}}>Time:</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.start_time}</Text>
<Text style={{color:'black',marginLeft:5}}>{props.item.end_time}</Text>
</View>}
</View>
)
}
export default Date_time;
I am calling component in UserAttemp.js
I have made a component of Date_time in that I am trying to set state in the body of function component but i am getting too manay render error due to the useState hook
I want to set State in the body of function Date_time.jjs component how to set?

Updating state outside the return function, makes it go in infinite loop. It will check the condition and update the state which will cause re-render then if will again check the condition and so on... it keeps re-rendering.
Remove the if statements and handle them in initial value of useState hook. Like-
const [dateBool,setDateBool]=useState(props.item?.start_date==props.item?.end_date ? true : props.item? false :true);
const [timeBool,setTimeBool]=useState(props.item?.start_time==props.item?.end_time ? true : props.item ? false:true);

Related

React Native RenderItem not working with custom renderItem

I created a custom renderItem using the React Native documentation as an example and it is not working, however, when using a simple component (commented in the script), it is working perfectly. I have tried to change some things around, but I can't make it work.
For the flatlist, I based my code on the react native example at https://reactnative.dev/docs/flatlist, using the flat-list-simple example, calling the function in the render item as renderItem={Function} but react-native does not recognize it, I appreciate any guidance on what I could change or if I am doing the whole thing wrong, thank you!
import { StyleSheet, Text, View, TouchableOpacity, FlatList } from 'react-native'
import React from 'react'
import Ionicons from 'react-native-vector-icons/Ionicons';
import VisitasHeader from './VisitasHeader';
const VisitasCard = ({visitas,titulo}) => {
// renderItem for FlatList
const CardFunction = (item) => {
<View style={{marginBottom:10}}>
<View style={styles.card_top}>
<View style={styles.holder}>
<View style={styles.icon}>
<Ionicons
name='ios-people-circle-sharp'
color='white'
size={48}
/>
</View>
<View style={styles.visitante}>
<Text style={styles.text_nombre}>{item.nombre} </Text>
<Text style={styles.text_cedula}>e-0000001</Text>
<View>
<Text style={styles.text_fecha}>2 de enero de 2022</Text>
</View>
</View>
</View>
</View>
<View style={styles.card_bottom}>
<TouchableOpacity style={styles.button_accept}>
<Text style={styles.button_text}>Aceptar</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button_reject}>
<Text style={styles.button_text}>Rechazar</Text>
</TouchableOpacity>
</View>
</View>
}
return (
<FlatList
ListHeaderComponent={<VisitasHeader title={titulo} />}
data={visitas}
keyExtractor={item => item.id}
renderItem={CardFunction}
// renderItem={({item}) => <View><Text>{item.nombre}</Text></View>} WORKS PERFECT WHEN USING THIS
ListEmptyComponent={<Text style={{textAlign:'center',paddingTop:10}}>No tiene visitas por aprobar.</Text>}
/>
)
}
export default VisitasCard
const styles = StyleSheet.create({
button_accept:{
backgroundColor:'green',
// margin:12,
padding:10,
borderRadius:12,
},
button_text:{
color:'white',
fontWeight:'bold',
},
button_reject:{
backgroundColor:'red',
// margin:12,
padding:10,
borderRadius:12,
},
card_bottom:{
height:50,
flexDirection:'row',
alignItems:'center',
justifyContent:'center',
borderWidth:1,
borderColor:'#3959ea',
borderBottomLeftRadius:8,
borderBottomRightRadius:8,
justifyContent:'space-evenly'
},
card_top:{
height:100,
backgroundColor:'#3959ea',
borderTopLeftRadius:8,
borderTopRightRadius:8,
alignItems:'center',
justifyContent:'center',
},
holder:{
flexDirection:'row',
},
icon:{
padding:10,
alignItems:'center',
margin:12,
},
text_cedula:{
color:'white',
fontSize:18,
textTransform:'uppercase',
fontWeight:'600',
},
text_nombre:{
color:'white',
fontSize:24,
textTransform:'capitalize',
fontWeight:'800',
// ellipsizeMode:'head',
// numberOfLines:1,
},
text_fecha:{
color:'white'
},
visitante:{
flex:2,
justifyContent:'center',
alignItems:'flex-start',
}
})
try add { item } and add return
const CardFunction = ({ item }) => {
return (
<View style={{ marginBottom: 10 }}>
<View style={styles.card_top}>
<View style={styles.holder}>
<View style={styles.icon}>
<Ionicons
name="ios-people-circle-sharp"
color="white"
size={48}
/>
</View>
<View style={styles.visitante}>
<Text style={styles.text_nombre}>{item.nombre} </Text>
<Text style={styles.text_cedula}>e-0000001</Text>
<View>
<Text style={styles.text_fecha}>2 de enero de 2022</Text>
</View>
</View>
</View>
</View>
<View style={styles.card_bottom}>
<TouchableOpacity style={styles.button_accept}>
<Text style={styles.button_text}>Aceptar</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button_reject}>
<Text style={styles.button_text}>Rechazar</Text>
</TouchableOpacity>
</View>
</View>
);
};

undefined is not an object (evaluating 'this.props.route.params.lead_tag_number.data') in react native

I am new to react native I want to use for loop for showing multiple data. which is come from previous screen from API.
here is my code. I want to show full return view in for loop multiple times. I am getting data in this => undefined is not an object (evaluating 'this.props.route.params.lead_tag_number.data')
class Browse extends Component {
constructor(props) {
super(props);
this.state ={
Email:"",
}
this.handleBackButtonClick = this.handleBackButtonClick.bind(this);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButtonClick);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButtonClick);
}
handleBackButtonClick() {
this.props.navigation.navigate("Browse");
return true;
}
state = {
categories: [],
error: [],
};
renderTab(tab) {
const { active } = this.state;
const isActive = active === tab;
return (
<TouchableOpacity
key={`tab-${tab}`}
onPress={() => this.handleTab(tab)}
style={[styles.tab, isActive ? styles.active : null]}
>
<Text size={16} medium gray={!isActive} secondary={isActive}>
{tab}
</Text>
</TouchableOpacity>
);
}
render() {
const { profile, navigation } = this.props;
const tabs = [""];
const route = this.props
for (let i = 0; i < this.props.route.params.data.length; i++) {
return (
<View style={{alignItems:"center", justifyContent:"center", }}>
<View style={styles.header}>
<Ionicons style={{paddingRight:290}} name="arrow-back" size={40}
color="black" onPress={() => navigation.navigate("Browse")} />
</View>
<Block>
<Block flex={false} row center space="between" style={styles.header}>
<Entypo style={{marginLeft:250}} onPress={() => this.props.navigation.toggleDrawer()} name="menu" size={30} color="black" />
</Block>
<Block flex={false} row style={styles.tabs}>
{tabs.map((tab) => this.renderTab(tab))}
</Block>
</Block>
<View style={{alignItems:"center", justifyContent:"center",height:140, width:"90%", marginTop:30}}>
<TouchableOpacity onPress={() => navigation.navigate("FormItems")}>
<Card center middle shadow style={{ height:80, width:"100%" }} >
<Text medium height={15} size={14}style={{ fontWeight: "bold", paddingRight:190}}>
{this.props.route.params.lead_tag_number.data[i]}
</Text>
</Card>
</TouchableOpacity>
</View>
</View>
)
}
}
}
Maybe it's problem with your for loop because you using for loop with params.data
for (let i = 0; i < this.props.route.params.data.length; i++)
and access data with params.lead_tag_number.data
this.props.route.params.lead_tag_number.data[i]
But this is not the right way to showing multiple data you can show with map function like this
render() {
const { profile, navigation } = this.props;
const tabs = [""];
const route = this.props
return (
<View style={{alignItems:"center", justifyContent:"center", }}>
<View style={styles.header}>
<Ionicons style={{paddingRight:290}} name="arrow-back" size={40}
color="black" onPress={() => navigation.navigate("Browse")} />
</View>
<Block>
<Block flex={false} row center space="between" style={styles.header}>
<Entypo style={{marginLeft:250}} onPress={() => this.props.navigation.toggleDrawer()} name="menu" size={30} color="black" />
</Block>
<Block flex={false} row style={styles.tabs}>
{tabs.map((tab) => this.renderTab(tab))}
</Block>
</Block>
{/*Use map on data as you want to show*/}
{this.props.route.params.data.map(item =>
<View style={{alignItems:"center", justifyContent:"center",height:140, width:"90%", marginTop:30}}>
<TouchableOpacity onPress={() => navigation.navigate("FormItems")}>
<Card center middle shadow style={{ height:80, width:"100%" }} >
{/*Use item*/}
<Text medium height={15} size={14}style={{ fontWeight: "bold", paddingRight:190}}>
{item}
</Text>
</Card>
</TouchableOpacity>
</View>
)}
</View>
)
}

react native: modal is not displaying

I am new to react-native and I am trying to display modal in react-native with following code
<View>
<View onPress={() => {this.toggleModal(true) }} onBackdropPress={ () =>
{this.hideModal(false)}}>
<View>
<OcticonsIcons name='plus' size={19}/>
<Text>QUICK ACTION</Text>
</View>
<View>
<View>
<Image source={require('../images/truck.png')}
/>
<Image source={require('../images/taxi(1).png')}
/>
<Image source={require('../images/tour.png')}
/>
</View>
</View>
</View>
</View>
<Modal visible={this.state.isModalVisible} animationType = "slide" transparent =
{false}>
<View style={{ flex: 1 }}>
<Text style={{ fontWeight:'bold', fontSize: 20, color: '#f79334', marginTop: 15
}} > Services </Text>
</View>
</Modal>
toggleModal(visible){
this.setState({ isModalVisible: visible });
}
hideModal(visible){
this.setState({ isModalVisible: visible })
}
but it's not working, can anyone tell me what wrong with my code, thank you.
The thing is you cant have onPress function on components, its solely for just showing. To use onPress you have to use TouchableOpacity.
Check the code below :
<View>
<TouchableOpacity onPress={() => {this.toggleModal(true) }} onBackdropPress={ () =>
{this.hideModal(false)}}>
<View>
<OcticonsIcons name='plus' size={19}/>
<Text>QUICK ACTION</Text>
</View>
<View>
<View>
<Image source={require('../images/truck.png')}
/>
<Image source={require('../images/taxi(1).png')}
/>
<Image source={require('../images/tour.png')}
/>
</View>
</View>
</TouchableOpacity>
</View>
<Modal visible={this.state.isModalVisible} animationType = "slide" transparent =
{false}>
<View style={{ flex: 1 }}>
<Text style={{ fontWeight:'bold', fontSize: 20, color: '#f79334', marginTop: 15
}} > Services </Text>
</View>
</Modal>
toggleModal = (visible) =>{
this.setState({ isModalVisible: visible });
}
hideModal = (visible) => {
this.setState({ isModalVisible: visible })
}
Hope it helps. feel free for doubts

How to show selected value from modal on text component in react-native

How to set selected value from modal on text component in react-native.
I am using modal component from 'react-native'.
import { StyleSheet, View, Text, TouchableOpacity, Image,Modal,} from 'react-native'
<View style={styles.vwstyle}>
<Text style={styles.texthead}>You are Interested in</Text>
<View style={styles.vwside}>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {
}}>
<View style={styles.vwmodal}>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text style={styles.txtmodal}>Man</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text style={styles.txtmodal}>Woman</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Text style={styles.txtmodal}>Everyone</Text>
</TouchableOpacity>
</View>
</Modal>
<TouchableOpacity
style={{flexDirection:'row'}}
onPress={() => {this.setModalVisible(true);}}>
<Text style={styles.txtselected}>Woman</Text>
<Image
source={require('../Images/rightarrow.png')} style={{ height: 20, width: 20, marginTop: 8, marginRight: 5 }} />
</TouchableOpacity>
</View>
</View>
You can use state to hold the values being pressed. I am including a code snippet here for your reference.
constructor(props) {
super(props);
this.state = {
otherStateVariables..... ,
pressedOption: ""
}
}
render() {
<View style={styles.vwstyle}>
<Text style={styles.texthead}>You are Interested in</Text>
<View style={styles.vwside}>
<Modal
animationType="fade"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {
}}>
<View style={styles.vwmodal}>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
/* Add this line to set your state on onPress handler*/
this.setState({pressedOption:"Man"})
}}>
<Text style={styles.txtmodal}>Man</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
/* Add this line to set your state on onPress handler*/
this.setState({pressedOption:"Woman"})
}}>
<Text style={styles.txtmodal}>Woman</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.touchmodal}
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
/* Add this line to set your state on onPress handler*/
this.setState({pressedOption:"Everyone"})
}}>
<Text style={styles.txtmodal}>Everyone</Text>
</TouchableOpacity>
</View>
</Modal>
<TouchableOpacity
style={{flexDirection:'row'}}
onPress={() => {this.setModalVisible(true);}}>
<Text style={styles.txtselected}>Woman</Text>
<Image
source={require('../Images/rightarrow.png')} style={{ height: 20, width: 20, marginTop: 8, marginRight: 5 }} />
</TouchableOpacity>
</View>
</View>
}
After setting the state, you can use that state variable anywhere in your code by using
this.state.pressedOption

Open ListView Photos in Modal

I want to use Modal with ListView and open That in renderRow(rowData){} Area But Does not open.
That is okey in render() Area But I Got: a red Screen Can't Find Variable: rowData
How Can I Fix That?
My Code:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableHighlight, ListView, Image, Modal, Linking } from 'react-native';
import photosData from '../dataset/Photos'
var Dimensions = require('Dimensions')
var { width, height } = Dimensions.get('window')
export default class MyListView extends React.Component {
constructor(props) {
super(props)
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
dataSource: ds.cloneWithRows(photosData),
modalVisible: false,
}
}
setModalVisible(visible) {
this.setState({ modalVisible: visible });
}
renderRow(rowData) {
const img = rowData.image
return (
<TouchableHighlight style={styles.containerCell}
// onPress={() => Linking.openURL(img)}
onPress={() => { this.setModalVisible(true) }}
>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }}
/>
<View style={styles.footerContainer}>
<View
style={styles.imageUser}
>
<Image
style={styles.imageAvatar}
// source={{ uri: rowData.user }}
source={require('../assets/icons/footer-avatar.png')}
/>
</View>
<View style={styles.footerTextContainer}>
<Text style={{ color: 'blue' }} //I can see my photos in webview
onPress={() => Linking.openURL(img)}>
Google
</Text>
<Text style={styles.text}>{rowData.food}</Text>
<Text style={[styles.text, styles.textTitle]}>{rowData.title}</Text>
<Text style={[styles.text, styles.textBy]}>By {rowData.by}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
render() {
const img = rowData.image
return (
<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { alert("Modal has been closed."), this.setModalVisible(!this.state.modalVisible) }}
>
<View style={{ marginTop: 22 }}>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }} // I can'ttttttttttt see my photos in Modal
/>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<ListView
style={styles.listContainer}
renderRow={this.renderRow.bind(this)}
dataSource={this.state.dataSource}
/>
</View>
);
}
}
I have pasted your code, it seem you have minor syntax error of closing bracket but I hope it is just copy-paste mistake.
First thing, you should not place your your Modal in renderRow function, it can create problem sometimes with styling and data. You can place it in main render() method.
Add function call to your rendering method if data is available and set this.setModalVisible(true).
Example:
render() {
return(
<View>
{/* other code */}
<Modal
animationType={'slide'}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { this.setModalVisible(false); } }
>
<View style={{ marginTop: 22 }}>
{(/*add some condition to check availability of data */)
? this.renderRow() // rendering function
: NULL}
</View>
</Modal>
</View>
);
}
EDIT after OP changed question:
Please find full code with my comment (not tested just added logic to work-around)
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableHighlight, ListView, Image, Modal, Linking } from 'react-native';
import photosData from '../dataset/Photos'
var Dimensions = require('Dimensions')
var { width, height } = Dimensions.get('window')
export default class MyListView extends React.Component {
constructor(props) {
super(props)
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 })
this.state = {
dataSource: ds.cloneWithRows(photosData),
modalVisible: false,
currentImage: ''
}
}
setModalVisible(visible, img) {
this.setState({ modalVisible: visible, currentImage: img }); // set current image path to show it in modal
}
renderRow(rowData) {
const img = rowData.image
return (
<TouchableHighlight style={styles.containerCell}
// onPress={() => Linking.openURL(img)}
onPress={() => { this.setModalVisible(true, img) }} // pass image scr to function
>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: img }}
/>
<View style={styles.footerContainer}>
<View
style={styles.imageUser}
>
<Image
style={styles.imageAvatar}
// source={{ uri: rowData.user }}
source={require('../assets/icons/footer-avatar.png')}
/>
</View>
<View style={styles.footerTextContainer}>
<Text style={{ color: 'blue' }} //I can see my photos in webview
onPress={() => Linking.openURL(img)}>
Google
</Text>
<Text style={styles.text}>{rowData.food}</Text>
<Text style={[styles.text, styles.textTitle]}>{rowData.title}</Text>
<Text style={[styles.text, styles.textBy]}>By {rowData.by}</Text>
</View>
</View>
</View>
</TouchableHighlight>
)
}
render() {
// const img = rowData.image
return (
<View style={styles.container}>
<Modal
animationType={"slide"}
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => { alert("Modal has been closed."), this.setModalVisible(!this.state.modalVisible) }}
>
<View style={{ marginTop: 22 }}>
<View>
<Image
// resizeMode={Image.resizeMode.contain}
// resizeMethod={"scale"}
style={{ width: width, height: 180, }}
source={{ uri: this.state.currentImage }} // use currentImage scr to show on clicking list item
/>
<TouchableHighlight onPress={() => {
this.setModalVisible(!this.state.modalVisible)
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
<ListView
style={styles.listContainer}
renderRow={this.renderRow.bind(this)}
dataSource={this.state.dataSource}
/>
</View>
);
}
}