Reputation: 832
I have a HomeScreen component which has button. I am trying to popup a modelview(Seperate component ie PopUpView) on the button click. In PopUpView i am sending its visibility as prop (isVisible).On the click of the button i am trying to change the state value popUpIsVisible from false to true. Hoping that this would re-render and popup my model view(Note this is working fine if i explicitly pass true). However with the state change it look like the render function is not being called and the popUp is not being displayed. Thanks for your help in advance
import React from 'react';
import { View, StyleSheet, Text, Button, TouchableHighlight, Alert, Dimensions} from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import PopUpView from './src/PopUpView';
class HomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
popUpIsVisible: false,
};
}
setPopUpIsVisible(isVisible){
this.setState({popUpIsVisible: isVisible });
}
render() {
this.setPopUpIsVisible = this.setPopUpIsVisible.bind(this);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor:"blue" }}>
<Text>Home Screen</Text>
<PopUpView isVisible={this.state.popUpIsVisible}/>
<Button onPress={() => {this.setPopUpIsVisible(true)}} title="Open PopUp Screen"/>
</View>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
PopUpView.js
import React from 'react';
import { View, Modal,StyleSheet, Text, TouchableOpacity, Dimensions} from 'react-native';
import { TabView, TabBar,SceneMap } from 'react-native-tab-view';
import Icon from 'react-native-vector-icons/SimpleLineIcons';
const FirstRoute = () => (
<View style={{ flex: 1, backgroundColor: '#ff4081' }} />
);
const SecondRoute = () => (
<View style={{ flex: 1, backgroundColor: '#673ab7' }} />
);
const ThirdRoute = () => (
<View style={{ flex: 1, backgroundColor: '#673ab7' }} />
);
export default class PopUpView extends React.Component {
constructor(props) {
super(props);
this.state = {
modalVisible:this.props.isVisible,
index: 0,
routes: [
{ key: 'first', title: 'HIGHLIGHTS' },
{ key: 'second', title: 'AMENITIES' },
{ key: 'third', title: 'FACILITIES' },
],
};
}
setModalVisible(visible) {
this.setState({modalVisible: visible});
}
renderHeader = props => <TabBar
{...props}
indicatorStyle={{backgroundColor: 'red'}}
tabStyle={styles.bubble}
labelStyle={styles.noLabel}
/>;
render() {
return (
<Modal
animationType="slide"
transparent={true}
visible={this.state.modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={styles.container}>
<View style={styles.navBar}>
<Text style={styles.navBarTitle}>Test</Text>
<TouchableOpacity
onPress={() => {
this.setModalVisible(!this.state.modalVisible);
}}>
<Icon style={styles.closeButton} name="close" size={35} color="grey" />
</TouchableOpacity>
</View>
<TabView
navigationState={this.state}
renderScene={SceneMap({
first: FirstRoute,
second: SecondRoute,
third: ThirdRoute,
})}
onIndexChange={index => this.setState({ index })}
initialLayout={{ width: Dimensions.get('window').width }}
renderTabBar={props =>
<TabBar
{...props}
style={{ backgroundColor: 'white' }}
indicatorStyle={{backgroundColor: 'black'}}
tabStyle={styles.bubble}
labelStyle={styles.label}
/>
}
/>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
margin: 50,
marginLeft: 20,
marginRight: 20,
marginBottom: 20,
backgroundColor: "white",
borderWidth: 1,
borderColor: "grey",
flexDirection: 'column'
},
navBar:{
height:70,
justifyContent: 'space-between',
alignItems: 'center',
flexDirection: 'row',
borderBottomColor: 'lightgrey',
borderBottomWidth: 1,
},
navBarTitle:{
fontSize: 25,
fontFamily: 'Optima',
paddingLeft:15,
},
closeButton:{
paddingRight:12,
},
label: {
color: 'black'
}
})
Upvotes: 0
Views: 1873
Reputation: 16334
The problem with your code is that you are using the state inside the PopUpView which does not change when you change the external prop. to fix this you should use the componentwillreceiveprops and update your state accordingly.
componentWillReceiveProps(nextProps){
if(this.props.isVisible!=nextProps.isVisible){
this.setState({modalVisible:nextProps.isVisible})
}
}
The better approach will be using the this.props.isVisible
as the visible
prop for the Model.
In this scenario you will have to pass a function as a prop to popupview which will set the popUpIsVisible to false.
Something like below
<PopUpView isVisible={this.state.popUpIsVisible}
onDismiss={()=>{this.setState({popUpIsVisible:false})}}/>
You can call the onDismiss inside the child as
<Modal visible={this.props.isVisible}>
<TouchableHighlight
onPress={() => {
this.props.onDismiss();
}}>
<Text>Hide Modal</Text>
</TouchableHighlight>
</Modal>
The second approach is better as the visibility of the child is controlled by the parent.
Upvotes: 1
Reputation: 3383
Add below line into constructor after state defining
this.setPopUpIsVisible = this.setPopUpIsVisible.bind(this);
Upvotes: 0