Rendering a React Modal from Another Component
Tags: react, javascript, webdev, tutorial
Published: 2021-10-31 03:43:50

Y'all, I just ventured into the land of modals in React, and my head is spinning. I just wanted a little success message to display when someone posts a review to my <a href="https://dev.to/jrrohrer/bookcritiq-a-react-project-1glj">BookCritiq app</a>. I'm going to share my solution here (before I forget) and hopefully this will help anyone else slogging through learning the same thing.

My app was built using Create-React-App and is styled with Bootstrap, so I used a Bootstrap modal component to create my modal.I placed my modal inside a functional component, since it's state will be handled by the parent component (the component that renders it).

```js
import React from 'react'
import {Modal, Button} from 'react-bootstrap'

const SuccessModal = (props) => {

  return (
    <div>
      // passing in the isOpen prop from the container
      <Modal show={props.isOpen}>
        <Modal.Header>
          <Modal.Title>Success!</Modal.Title>
        </Modal.Header>
        <Modal.Body>Thanks for your contribution!</Modal.Body>
        <Modal.Footer>
          // passing in the toggle function so that clicking the OK button closes the modal
          <Button variant="primary" onClick={props.toggle}>OK</Button>
        </Modal.Footer>
      </Modal>
    </div>
  )
}

export default SuccessModal;
```

I am going to handle the state for the modal component in my ReviewsContainer component. This container renders both my ReviewCreateForm and Reviews components. The trigger for the modal to appear will be the submit button on the ReviewCreateForm.

```js
// ReviewsContainer.js

class ReviewsContainer extends React.Component {
  // setting the initial state for the modal as hidden
  state = {
    showModal: false
  }
  // creating a toggle function that will be passed down to any children of this container that need to toggle the modal on or off
  toggleModal = () => {
    this.setState({ showModal: !this.state.showModal })
  }

  render () {
    return (
      <div>
        <Switch>
          // pass the toggle function to the ReviewCreateForm
          <Route path='/books/:id/reviews/new' render={(routeProps) => <ReviewCreateForm {...routeProps} book={this.props.book} toggle={this.toggleModal}/> } />
        </Switch>
        <Reviews reviews={this.props.book[0].attributes.reviews}/>
        // Render the modal and pass down the state and toggle function as props.
        <SuccessModal isOpen={this.state.showModal} toggle={this.toggleModal} />
      </div>
    )
  }
}

export default ReviewsContainer;
```

Finally, I am going to add the toggle function to my handleOnSubmit event handler inside of my review form:

```js
// ReviewCreateForm.js

  handleOnSubmit = (event) => {
    event.preventDefault();
    this.props.addReview(this.state, this.props.book[0].id, this.props.history);
    this.props.toggle();
  }
```

Most of the time I spent banging my head on the wall over figuring this out was because I was trying to allow the modal component to oversee it's own state. I forgot one of the main characteristics of React: The data flows down.

*Cover Photo by <a href="https://unsplash.com/@mikeanywhere?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Mike Lewis HeadSmart Media</a> on <a href="https://unsplash.com/s/photos/waterfall?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>*