This is an example of creating a reusable modal component with React that supports CSS animations. You can find the source code here.

It would be fairly easy to create a specific modal component that is mounted and unmounted by toggling a bit of state in the parent component. However, what we want is a little more complex:

We want a reusable modal component, that you just wrap around the modal’s contents, add some props, and it works, so you don’t have to create a new component for each modal in your app.

Animation support: We want to be able to write some CSS selectors that correspond to the various stages of the modal’s lifecycle.

August 2018: Please note that this post was written for an older version of React. Changes in the code might be necessary to adapt it to the latest versions and best practices.

Components

First, we bring in React’s CSS Transition Group component:

var ReactCSSTransitionGroup = React . addons . CSSTransitionGroup ;

Next, we create the modal. This component automates the following:

It determines whether or not it should be shown using a prop.

It wraps its contents in a CSS Transition Group.

var Modal = React . createClass ({ render : function () { if ( this . props . isOpen ){ return ( < ReactCSSTransitionGroup transitionName = { this . props . transitionName } > < div className = "modal" > { this . props . children } < /div> < /ReactCSSTransitionGroup> ); } else { return < ReactCSSTransitionGroup transitionName = { this . props . transitionName } />; } } });

Note how we use this.props.children to extract the component’s body.

Rather than null when the modal is not open, we return an empty transition group. We need to do this to keep the transition group component isolated inside the modal, so the parent of the modal doesn’t have to instantiate it manually.

Now, for this example, we’ll create an App component to hold the state that tells React whether the modal is open, and a couple of methods to open and close it.

var App = React . createClass ({ getInitialState : function () { return { isModalOpen : false }; }, openModal : function () { this . setState ({ isModalOpen : true }); }, closeModal : function () { this . setState ({ isModalOpen : false }); }, render : function () { return ( < div className = "app" > < h1 > App < /h1> < button onClick = { this . openModal } > Open modal < /button> < Modal isOpen = { this . state . isModalOpen } transitionName = "modal-anim" > < h3 > My Modal < /h3> < div className = "body" > < p > This is the modal & apos ; s body . < /p> < /div> < button onClick = { this . closeModal } > Close modal < /button> < /Modal> < /div> ); } });

As you can see in render , all we had to do was wrap the contents of the modal in the Modal component, pass the state that determines whether its open, and give the CSS transition a name (We’ll use this later). Inside the body, we make insert a call to the closeModal method. There’s no need to bind anything.

Finally, we render the App component, and this concludes the JavaScript part of this example:

React . render ( < App />, document. body );

Animation

Most of the stylesheet is not important to this example, it’s just giving the app and modal components a shape. The important part is the CSS animation classes that React will use.

The enter selector sets the style for the component’s initial state before animation begins, and enter-active sets the final state:

. modal-anim-enter { opacity : 0.00 ; transform : scale( 0.7 ); transition : all 0.2 s ; } . modal-anim-enter . modal-anim-enter-active { opacity : 1 ; transform : scale( 1 ); }

leave and leave-active are the opposite: