How to get a React Bootstrap Modal to open and close using a button of your choice in a parent component
I was working on a site with some friends last week. We were using React-Bootstrap as a solution for out-of-the-box UI components. We all liked the idea of using modals for our pop-up menus and we wanted to use side tabs for navigation. The way the React-Bootstrap modal component is written, the button to open the modal is contained within the component itself. This can make things confusing if you’re trying to figure out how to place the component. If you’re familiar with React-Bootstrap and you’re just searching for the solution in a hurry, skip down to the picture of a stop sign to see my solution for this problem. If you’d like to read a little more about this problem, read on.
Start here if you don’t know about React-Bootstrap
React-Bootstrap is a front-end framework of components for react. If you use React and haven’t checked out React-Bootstrap, it’s worth the effort to get acquainted with it. It’s pretty easy to implement, you can follow the walk-through on their site here. I’ve never run into any problems getting React-Bootstrap working with my apps.
To install React-Bootstrap, use npm:
npm install react-bootstrap bootstrap
Select the components you’d like to use from their site and then, in your code, import each component you plan on using individually. In the case of the Modal:
import Modal from 'react-bootstrap/Modal'
or
import { Modal } from 'react-bootstrap';
In the documentation for each component, you’ll see sample implementation code for the components. These take the import libraries and build a lot of functionality for you to use. I think this is what makes React-Bootstrap so popular and powerful. Pick the code that’s closest to the functionality you want for a component and use it as a starting point for your implementation of the component. For the purposes of this post, let’s use the code for the Live Demo Modal:
import Modal from 'react-bootstrap/Modal'function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button><Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}render(<Example />);
… so now we have a component, Example
, that imports the Modal functionality from React Bootstrap and contains the sample code from the component as presented on the React-Bootstrap website. The code to open the Modal are the 3 lines right after the return
:
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
… this places a button where we place Example
in our app, and when we click it, we set show
in the Modal’s state to true via the setState hook. There are a couple of buttons in the sample code to close the Modal, they both have the onClick={handleClose}
to set show
back to false. The behaviors are set in the Modal tag:
<Modal show={show} onHide={handleClose}>
This works great, but it’s self-contained. The button is part of the Modal code. What if we want to open the modal from React-Bootstrap’s Tab
component?
The Tab component
<Tab.Container id="left-tabs-example" defaultActiveKey="first">
<Row>
<Col sm={3}>
<Nav variant="pills" className="flex-column">
<Nav.Item>
<Nav.Link eventKey="first">Tab 1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="second">Tab 2</Nav.Link>
</Nav.Item>
</Nav>
</Col>
<Col sm={9}>
<Tab.Content>
<Tab.Pane eventKey="first">
<Sonnet />
</Tab.Pane>
<Tab.Pane eventKey="second">
<Sonnet />
</Tab.Pane>
</Tab.Content>
</Col>
</Row>
</Tab.Container>
Just like in the picture abovce, the code sets up Tabs for navigation. Each <NavItem>
in the <Nav>
section corresponds to a <Tab.Pane>
in the <Tab.Content>
portion of the code. The goal here is to place our <Example>
Modal in such a way that we can open it up from a Tab.
Here’s what you need to know to get the Modal to open up with the Tab click
All you need to do to get the Modal to open up as desired it to move the show
hook, up from the Modal, <Example>
, to Tab
. Once show
and is in Tab
, you can pass it and its setState hook down as props to the Modal. So, in Tab
:
const [modalShow, setModalShow] = useState(false);
and in the Nav
section:
<Nav.Link
className="tab__link"
eventKey="modal"
onClick={() => setModalShow(true)}>
Show the Modal!</Nav.Link>
and in it’s corresponding Tab
:
<Tab.Pane eventKey="second"><Example
modalShow={modalShow}
setModalShow={setModalShow}/></Tab.Pane>
Note that we’re using setModalShow
directly and eliminating functionshandleClose
, and handleOpen
.
In the Example
Modal, we need to make a few changes. First change:
<Modal show={show} onHide={handleClose}>
to:
<Modal show={props.moadalShow}>
And replace both onClick={handleClose}
with onClick={props.setModalShow(false)}
. Remove the code for the opening button, and also remove the functions handleOpen
and handleClose
, and you’re all set.
Now, when a user clicks the Tab marked Show the Modal!
, they’ll open up the Modal, and when they click the x or close buttons on the component the Modal will close. Easy-peasy.
React-Bootstrap is one of many custom frameworks freely available to power-up our frontend development needs. This strategy of moving data to a higher component and passing it down to the component it controls, comes in handy a often and is worth getting familiar with just as much as the React-Bootstrap framework. Have an awesome week and happy coding!