I have a modal that shown on a button click and the modal is fetched from another component using prop.
In the modal there is a button to close the modal, How to close the modal onclick the button. I have tried but doesn't worked.
//InvalidUser
const InvalidUser = (props) => (
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log('closed')}
>
<View style={styles.modalBox}>
<View style={{width: 300}}>
<Text style={styles.text}>
{props.data}
</Text>
<TouchableOpacity
onPress={() =>
this.closeModal()
}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
);
//Login
export default class LoginFirst extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
modalVisible: false
};
}
nextBtn = () => {
let reg = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (this.state.email !== '') {
if (reg.test(this.state.email) === false) {
}
else {
this.setState({modalVisible: true});
}
}
}
render() {
let notRegistered = this.state.email+' is not recognized as a registered user. Please contact us for further assistance.';
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.scroller}>
<View
style={styles.inputSection}
>
<Text style={styles.label}>Email Address:</Text>
<View style={styles.section}>
<Image
style={styles.icon}
source={require('../../../../assets/user.png')}
/>
<TextInput
style={styles.input}
placeholder='johnsmith#gmail.com'
underlineColorAndroid='transparent'
onChangeText={(text) => this.setState({email:text})}
/>
</View>
<TouchableOpacity
style={styles.button}
onPress={() =>
this.nextBtn()
}
>
<Text style={styles.next}>Next</Text>
</TouchableOpacity>
</View>
</ScrollView>
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
/>
</View>
);
}
}
The above code is perfectly displaying the modal, but I cannot close the modal. Is there any way to close.
Please have a look into below image.
from parent component, create closeModal function and pass it to InvalidUserModal
closeModal = () => {
this.setState({modalVisible: false});
}
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
closeModal={this.closeModal}
/>
and call it inside InvalidUserModal on press the button
<TouchableOpacity onPress={props.closeModal}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
For parent, pass the closeModal method as a props to your component
class LoginFirst extends Component {
closeModal = () => {
this.setState({modalVisible: false});
}
render() {
return (
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
closeModal={this.closeModal}
/>
)
}
}
For your modal component
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log('closed')}
>
<TouchableOpacity onPress={props.closeModal}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
</Modal>
Related
****I have a react native page app with 2 inputs. ****
I want to show the "submit" button once all of the 2 fields have a value.
(button is invisible until the 2 input fields have value)
this is my page code :
class Page3 extends Component {
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.question1Stack}>
<Text style={styles.question1}>Question1</Text>
<ImageBackground
source={require("./assets/undraw_Friends_online_re_r7pq.png")}
resizeMode="contain"
style={styles.image}
imageStyle={styles.image_imageStyle}
>
<TouchableOpacity onPress={() =>{this.props.navigation.navigate('Page2')}}>
<Icon name="chevron-left" style={styles.icon1}></Icon>
</TouchableOpacity>
</ImageBackground>
</View>
<TouchableOpacity
title="submit"
onPress={() => {
this.props.navigation.navigate('Page4');
}}>
<Text style={styles.next}>
Next
</Text>
</TouchableOpacity>
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
></MaterialHelperTextBox1>
</View>
);
}
}
these are my input fields :
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
></MaterialHelperTextBox1>
you most define to two state for two TextInput , than set TextInput value in onChangeText check value is not null and valid , set true states for check, I don't know you use MaterialHelperTextBox1 by witch component but code maybe like this:
class Page3 extends Component {
constructor(props) {
super(props);
this.state = {
checkInput1:false,
checkInput2:false,
inputValue1:'',
inputValue2:'',
};
};
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.question1Stack}>
<Text style={styles.question1}>Question1</Text>
<ImageBackground
source={require("./assets/undraw_Friends_online_re_r7pq.png")}
resizeMode="contain"
style={styles.image}
imageStyle={styles.image_imageStyle}
>
{checkInput1 && checkInput2 ?
<TouchableOpacity onPress={() =>
{this.props.navigation.navigate('Page2')}}>
<Icon name="chevron-left" style={styles.icon1}></Icon>
</TouchableOpacity>
:
null
}
</ImageBackground>
</View>
<TouchableOpacity
title="submit"
onPress={() => {
this.props.navigation.navigate('Page4');
}}>
<Text style={styles.next}>
Next
</Text>
</TouchableOpacity>
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
onChangeText={value => {this.setstate({inputValue1:value});
_checkInputIsValid1();}}
defaultValue={this.state.inputValue1}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
onChangeText={value => {this.setstate({inputValue2:value});
_checkInputIsValid2();}}
defaultValue={this.state.inputValue1}
></MaterialHelperTextBox1>
</View>
);
}
}
_checkInputIsValid1(){
//check your rules for input1 there if true set state checkInput1 as true
}
_checkInputIsValid2(){
//check your rules for input2 there if true set state checkInput2 as true
}
I am trying to render the child component on onPressevent, the console.log works fine but components in the return function doesn't works.
Parent component:
onPress = (img,title,content) => {
this.setState({
show:true,
img:img,
title:title,
content:content
})
render() {
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => this.onPress(item.urlToImage,item.title,item.content)}
>
<View style={styles.picsCont}>
<Image style={styles.pics} source={{uri: item.urlToImage}}/>
<Text style={{color:'white', fontSize: 15, fontWeight: '700', paddingTop:10}}>
{item.title}
</Text>
</View>
</TouchableOpacity>
)}
keyExtractor={item => item.title}
/>
{this.state.show ?
<NewsView
img={this.state.img}
title={this.state.title}
content={this.state.content}
/> :
null
}
</View>
);
}
}
Child Component:
export default class NewsView extends Component {
render() {
console.log(this.props.img)
return (
<View style={styles.container}>
<Image style={styles.picsCont} source={{uri:this.props.img}} />
<Text style={styles.news}>{this.props.title}</Text>
<Text style={styles.news}>{this.props.content}</Text>
</View>
)
}
}
Thanks for the help...!
It might be the styles. If your child component has position:'absolute', it´s probably under your parent component, you can try to put on your child component view zIndex:10
I am studying React Naive by making a ToDo list.
I want to change the ToDo app to a Comment List that has comment one to another.
First attempt worked correctly:
First attempt
But, all users changed after second attempt.
Second attempt
Now, parent passes props to child by using {this.state.pick} and {this.state.key} , but child would change if parent's props changed.
Is there any way to change the parent props without changing child props?
Comment.js:
export default class CommentIndex extends Component<{}> {
constructor(props) {
super(props);
this.state = {
head: [],
list: [],
pick: [],
};
}
_onPress = (text) => {
const list = [].concat(this.state.list);
list.push({
key: Date.now(),
text: text,
done: false,
});
this.setState({
list,
});
}
render() {
const {
head,
list,
pick,
} = this.state;
var data = [["User1", "User2", "User3"],];
return (
<View style={styles.container}>
<View style={styles.dropdownHeader}>
<View style={styles.dropdown}>
<DropdownMenu
style={{flex: 1}}
bgColor={'white'}
tintColor={'#666666'}
activityTintColor={'green'}
handler={(selection, row) => this.setState({head: data[selection][row]})}
data={data}
>
<View style={styles.userHeader}>
{ this.state.head === 'User1' && <User1 /> }
{ this.state.head === 'User2' && <User2 /> }
{ this.state.head === 'User3' && <User3 /> }
</View>
</DropdownMenu>
</View>
</View>
<Text>To Do</Text>
<View style={styles.main}>
<View style={styles.post}>
<View style={styles.dropdown}>
<View style={{height: 0}} />
<DropdownMenu
bgColor={'white'}
tintColor={'#666666'}
activityTintColor={'green'}
handler={(selection,row) => this.setState({pick: data[selection][row]})}
data={data}
>
<View style={styles.user}>
{ this.state.pick === 'User1' && <User1_photo /> }
{ this.state.pick === 'User2' && <User2_photo /> }
{ this.state.pick === 'User3' && <User3_photo /> }
</View>
</DropdownMenu>
</View>
<View style={styles.postinput}>
<CommentInput onPress={this._onPress} />
</View>
</View>
<View style={styles.CommentListContainer}>
<FlatList
style={styles.CommentList}
data={list}
renderItem={({ item }) => <CommentItem {...item} head={this.state.head} pick={this.state.pick}/>}
/>
</View>
</View>
</View>
);
}
}
CommentInput:
export default class CommentInput extends Component {
constructor(props) {
super(props);
this.ref = {};
}
_onPress = () => {
this.props.onPress(this.ref._lastNativeText);
this.ref.setNativeProps({ text: '' });
}
render() {
const {
onPress,
} = this.props;
return (
<View style={styles.container}>
<TextInput
style={styles.textInput}
ref={(ref) => { this.ref = ref; }}
/>
<TouchableOpacity
style={styles.button}
onPress={this._onPress}
>
<Text style={styles.buttonText}>追加</Text>
</TouchableOpacity>
</View>
);
}
}
You could implement the shouldComponentUpdate method on the child. This will block a re-render (with the new properties) when you want.
Please find my code below and help me for adding item click listener for the items in the grid view. Please find the link which I followed library link.
And I need to display the name in an alert when the user clicks on each item in the gridlist. Styles are not included in the code
Thanks in Advance
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
TouchableWithoutFeedback
} from 'react-native';
import GridLayout from 'react-native-layout-grid';
class HomeScreen extends Component {
renderGridItem = (props) => (
<View style={styles.item} >
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</View>
);
render() {
const items = [];
for (let x = 1; x <= 30; x++) {
items.push({
name: `Grid ${x}`
});
}
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Grid Layout
</Text>
<View style={styles.flex}>
<GridLayout
items={items}
itemsPerRow={2}
renderItem={this.renderGridItem}>
</GridLayout>
</View>
</View>
);
}
}
export default HomeScreen;
Instead of using <View> in your renderGridItem, you could use one of the touchables component (react native doc).
For example with <TouchableOpacity >:
renderGridItem = (props) => (
<TouchableOpacity style={styles.item} onPress={() => this.showAlert(props.name)}>
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</TouchableOpacity>
);
showAlert = (name) => {
Alert.alert(
'Alert Title',
`The user name is: ${name}`,
[
{text: 'OK', onPress: () => console.log('OK Pressed')},
],
{ cancelable: false }
)
}
Why don't you wrap renderGridItem in a TouchableWithoutFeedback?
renderGridItem = (props) => (
<TouchableWithoutFeedback onPress={()=> Alert.alert(props.name)}>
<View style={styles.item} >
<View style={styles.flex} />
<Text style={styles.name} >
{props.name}
</Text>
</View>
<TouchableWithoutFeedback />
);
Also you will need to import Alert from react-native.
I am newbie to react native developing. I want to close the modal component on pressing outside the modal in reactnative. Below is my code.
state = {
visibleModal : false,
};
_hideModal(){
this.setState({
visibleModal: true,
})
}
render(){
return(
<View style={
[styles.container,
{backgroundColor: this.state.visibleModal ? 'rgba(47, 60, 73, 0.75)': 'white'}
]}>
<Text>Text Behind Modal</Text>
{ this._renderButton('BUTTON', () => this.setState({ visibleModal: true}) ) }
<TouchableWithoutFeedback onPress={() => {this._hideModal()}}>
<Modal animationType={"slide"}
transparent={true}
visible={this.state.visibleModal}>
<View style={styles.modalContent}>
<Row />
</View>
</Modal>
</TouchableWithoutFeedback>
</View>
);
}
}
Just add this prop in Modal
onRequestClose={() => { this.visibleModal(false); } }
It will close your modal on pressing back button
<Modal animationType={"slide"}
transparent={true}
visible={this.state.visibleModal}
onRequestClose={() => { this.visibleModal(false); } }
>
EDIT
Above code will work only on Android as per the document.
For both,
You can add custom button to close modal
<TouchableOpacity
onPress={() => {
this.setState({visibleModal: false})
} }>
<Image
style={[styles.modalBackIcon]}
source={require('../../theme/images/back-icon.png')} />
</TouchableOpacity>
<Modal animationType={"slide"}
transparent={true}
visible={this.state.visibleModal}>
<TouchableWithoutFeedback onPress={() => {this.close_modal()}}>
<View style={styles.modalContent}>
....
</View>
</TouchableWithoutFeedback>
</Modal>
this is sample of my code when you tap outside to close your modal
than so close_modal function visibleModal get false value
for exp.
this.setState({ visibleModal: false });
Question :
To close modal when clicking outside the modal.
Solution:
Just remove function call on TouchableWithoutFeedback,it will work..
<TouchableWithoutFeedback onPress={() => {}}>
<Modal animationType={"slide"}
transparent={true}
visible={this.state.visibleModal}>
<View style={styles.modalContent}>
<Row />
</View>
</Modal>
</TouchableWithoutFeedback>