DEV Community 👩‍💻👨‍💻

DEV Community 👩‍💻👨‍💻 is a community of 968,547 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Rendering a React Modal from Another Component
Jessie Rohrer
Jessie Rohrer

Posted on

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

Top comments (1)

Collapse
 
rajivchaulagain profile image
Rajiv Chaulagain

Amazing example

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.