React js: Open same modal from different components

19,267

Solution 1

I highly recommend the approach that Dan Abramov described in How can I display a modal dialog in Redux that performs asynchronous actions? . Basically, have a central component that is responsible for displaying modals, and dispatch actions that give the name of the modal to open and any values to pass along as props.

Solution 2

You can have the state inside the modal and expose two functions to open/close modal which will change the state. Those functions can be accessed via refs in other components.See the example below.

ModalWindow.js

import Modal from 'Bootstrap/Modal'

class ModalWindow extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showModal: false,
    }
  }
  show() {
    this.setState({
      showModal: true,
    })
  }
  hide() {
    this.setState({
      showModal: true,
    })
  }
  render() {
    return <Modal
    show={this.state.showModal}
    container={this.props.container}
    bsSize='small'>
      < Modal.Header closeButton = "true" >
      < Modal.Title id = "contained-modal-title" >
      Login < /Modal.Title> < /Modal.Header> < Modal.Body >
      Login Here < /Modal.Body> < /Modal>
  }
}

export default ModalWindow

A.js, B.js, C.js

import ModalWindow from 'ModalWindow.js'

class A extends Component {
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    this.refs.modal.show() //to show the modal
    this.refs.modal.hide() //to hide the modal
  }
  render() {
    return <ModalWindow container={this} ref = "modal" / >
  }
}

export default A
Share:
19,267
iamsaksham
Author by

iamsaksham

Updated on July 16, 2022

Comments

  • iamsaksham
    iamsaksham almost 2 years

    I want to open a Modal, say 'modal for user login', from different components in my React app. For ex: I want the modal to open from A.js, B.js and C.js. So I made a new component ModalWindow.js which contains the modal and I imported it in A.js, B.js and C.js.

    Now the issue is that I got to maintain state showModal: false in all 3 components for Modal to show/hide. Is there anyway that I have to maintain a single state.

    One way is that I maintain state in the parent component. But is there any better way possible?

    X.js

    import A from 'A.js'
    import B from 'B.js'
    import C from 'C.js'
    
    class X extends Component {
      return(
        render{
          <div>
            <A />
            <B />
            <C />
          </div>
        }
      )
    }
    
    export default X
    

    A.js

    import ModalWindow from 'ModalWindow.js'
    
    class A extends Component {
      constructor(props) {
        super(props);
        this.state = {
          showModal: false
        };
      }
      return(
        render{
          <ModalWindow show={this.state.showModal} container={this}/>
        }
      )
    }
    
    export default A
    

    B.js

    import ModalWindow from 'ModalWindow.js'
    
    class B extends Component {
      constructor(props) {
        super(props);
        this.state = {
          showModal: false
        };
      }
      return(
        render{
          <ModalWindow show={this.state.showModal} container={this}/>
        }
      )
    }
    
    export default B
    

    C.js

    import ModalWindow from 'ModalWindow.js'
    
    class C extends Component {
      constructor(props) {
        super(props);
        this.state = {
          showModal: false
        };
      }
      return(
        render{
          <ModalWindow show={this.state.showModal} container={this}/>
        }
      )
    }
    
    export default C
    

    ModalWindow.js

    import Modal from 'Bootstrap/Modal'
    
    class ModalWindow extends Component {
      return(
        render{
          <Modal
          show={this.props.showModal}
          container={this.props.container}
          bsSize='small'
        >
          <Modal.Header closeButton="true">
            <Modal.Title id="contained-modal-title">
              Login
            </Modal.Title>
          </Modal.Header>
          <Modal.Body>
            Login Here
          </Modal.Body>
        </Modal>
        }
      )
    }
    
    export default ModalWindow