Rendering a React Modal from Another Component

jrrohrer

Jessie Rohrer

Posted on October 31, 2021

Rendering a React Modal from Another Component

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 BookCritiq app. 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).

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;
Enter fullscreen mode Exit fullscreen mode

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.

// 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;
Enter fullscreen mode Exit fullscreen mode

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

// ReviewCreateForm.js

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

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 Mike Lewis HeadSmart Media on Unsplash

💖 💪 🙅 🚩
jrrohrer
Jessie Rohrer

Posted on October 31, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related