9

I have an App with Home Screen, in this screen I'm rendering a Modal which opens on button press, inside the Modal I have a button that is supposed to navigate me to another screen, it's navigating correctly but when I navigate to another screen the modal doesn't disappear, how can i hide it?

Adding the code to demonstrate

Home:

import React, { Component } from 'react';
import Modal from './Modal';

class Home extends Component {
  state = {
    isModalVisible: false
  };

  toggleModal = () =>
    this.setState({ isModalVisible: !this.state.isModalVisible });

  render() {
    const { navigate } = this.props.navigation;

    <Modal
    visible={this.state.isModalVisible}
    navigation={this.props.navigation}
    />
    );
  }
}

export default Home;

Modal:

import React, { Component } from "react";
import Modal from "react-native-modal";

class Modal extends Component {

  render() {
    const { navigate } = this.props.navigation;

    return (
        <Modal
        isVisible={this.props.visible}>
          <Button onPress={() => {navigate('Main')}}>
            >Button</Text>
          </Button>
        </Modal>
    );
  }
}

export default Modal;
Pritish Vaidya
  • 21,561
  • 3
  • 58
  • 76
Judy M.
  • 243
  • 1
  • 4
  • 12

3 Answers3

5

Ideally you should wait for the setState to finish inside the callback and then navigate to the screen, since the methods are async and may disrupt the state if navigate is called before setState has finished completing.

Also parent should control the state of the child.

Home

onNavigate = () => {
  this.setState({isModalVisible: false}, () => this.props.navigation.navigate('Main')
}

<Modal
    visible={this.state.isModalVisible}
    onNavigate={this.onNavigate}
 />

Modal

<Modal
  isVisible={this.props.visible}>
    <Button onPress={this.props.onNavigate}>
      <Text>Button</Text>
    </Button>
</Modal>
Pritish Vaidya
  • 21,561
  • 3
  • 58
  • 76
0

You should provide a reference to the variable that defines the visibility state of the modal component. You'll need to define a function hides the modal and pass the function reference to the modal component and execute it on press of the button along side with the navigation action.

Something on the lines of -

Your home screen should have a function like -

onModalClose = () => {this.setState({isModalVisible: false})}

then pass this as reference to the modal component like -

  <Modal
visible={this.state.isModalVisible}
navigation={this.props.navigation}
onModalClose={this.onModalClose}
/>

and call it on the onPress() method of the <Button/> component like-

          <Button onPress={() => {this.props.onModalClose(); navigate('Main')}}>

EDIT

Just noticed, since you already have a function that toggles the visibility of your modal, you need not define a new function. You can pass that function reference to the modal component itself.

  <Modal
visible={this.state.isModalVisible}
navigation={this.props.navigation}
onModalClose={this.toggleModal}
/>
Aseem Upadhyay
  • 4,279
  • 3
  • 16
  • 36
0

I took Pritish Vaidya answer and made it usable for any screen.

Home

import React, { Component } from 'react';
import Modal from './Modal';

class Home extends Component {
  state = {
    isModalVisible: false
  };

  toggleModal(screenName) {
    this.setState({isModalVisible: !this.state.isModalVisible });
    if (screenName && screenName != '') {
       this.props.navigation.navigate(screenName);
    }
  }

  render() {
    <Modal
      visible={this.state.isModalVisible}
      onDismiss={(screenName) => { this.toggleModal(screenName); }}
    />
    );
  }
}

export default Home;

Modal:

class Modal extends Component {

    dismissScreen(screenName) {
        const dismissAction = this.props.onDismiss;
        dismissAction(screenName);
    }

    render() {
      return(
        <View style={{ flex: 1, padding: 20 }}>
            <Button
            title="Dismiss Modal"
            onPress={() => {this.dismissScreen();}}
            />
            <Button
            title="Navigate to Other Screen"
            onPress={() => {this.dismissScreen('ScreenName');}}
            />
        </View>
      );
    }
}
MontiRabbit
  • 1,020
  • 12
  • 17