UI 코딩

src/components/Modal/index.js

export { default } from './Modal';

src/components/Modal/Modal.js

import React from 'react';
import './Modal.scss';

const Modal = () => {
  return (
    <React.Fragment>
         <div className="Modal-overlay" />
      <div className="Modal">
        <p className="title">Modal Title</p>
        <div className="content">
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vel tempora nulla, non molestiae dicta ducimus. Et unde laborum eveniet ex quod doloribus quae, aliquam beatae atque, vero assumenda rem quo?
          </p>
        </div>
        <div className="button-wrap">
          <button> Confirm </button>
        </div>
      </div>
    </React.Fragment>
  )
}
export default Modal;

src/components/Modal/Modal.scss

.Modal-overlay{
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-color: rgba(0,0,0,0.16);
}
.Modal{
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 320px;
    border-radius: 10px;
    background-color: white;
    box-shadow: 0px 3px 6px rgba(0,0,0,0.16);
    & > * {
      &:first-child{
        margin-top: 16px;
      }
      margin-left: 16px;
      margin-right: 16px;
    }
    p.title{
      font-size: 16pt;
      font-weight: bold;
      color: #333;
    }
    .content{
      border-top: 1px solid #bebebe;
      margin-top: 16px;
      p{
        padding: 8px;
        font-size: 12pt;
        color: #999;
      }
    }

    .button-wrap{
      margin: 0;
      margin-top: 8px;
      button{
        width: 100%;
        padding: 12px 0;
        border-radius: 0 0 10px 10px;
        background-color: #ad7cef;
        font-size: 13pt;
        color: white;
        border: 0;
        cursor: pointer;
        &:hover{
          background-color: #7f49c8;
        }
        &:active{
          background-color: #7e49c8;
        }
      }
    }
  }

src/App.js

import React from 'react';
import Modal from './components/Modal';

class App extends React.Component{
  render() {
    return (
      <main className="App">
        <Modal />
      </main>
    )

  }
}
export default App;

UI완성
localhost_3000_.png

Modal Open/Close 기능 구현

src/App.js

import React from 'react';
import Modal from './components/Modal';

class App extends React.Component{

  constructor(props){
    super(props);
    this.state = {
      isModalOpen: false, 
    }
  }

  openModal = () => {
    this.setState({ isModalOpen: true });
  }

  closeModal = () => {
    this.setState({ isModalOpen: false }); 
  }

  render() {
    return(
      <main className="App">
        <button onClick={this.openModal}>Modal Open</button>
        <Modal isOpen={this.state.isModalOpen} close={this.closeModal} />
      </main>
    )

  }
}
export default App;

src/components/Modal/Modal.js

import React from 'react';
import './Modal.scss';

const Modal = ({ isOpen, close }) => {
  return (
    <React.Fragment>
    {
      isOpen ?
      <React.Fragment>
        <div className="Modal-overlay" onClick={close} />
        <div className="Modal">
          <p className="title">Modal Title</p>
          <div className="content">
            <p>
              Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vel tempora nulla, non molestiae dicta ducimus. Et unde laborum eveniet ex quod doloribus quae, aliquam beatae atque, vero assumenda rem quo?
            </p>
          </div>
          <div className="button-wrap">
            <button onClick={close}>Confirm</button>
          </div>
        </div>
      </React.Fragment>
      :
      null
    </React.Fragment>
  )
}
export default Modal;

잘 작동하는지 확인
localhost_3000_ (1).png

Modal Transition 추가

yarn add react-addons-css-transition-group

src/components/Modal/Modal.js

import React from 'react';
import './Modal.scss';
import ReactTransitionGroup from 'react-addons-css-transition-group';

const Modal = ({ isOpen, close }) => {
  return (
    <React.Fragment>
    {
      isOpen ?
      <ReactTransitionGroup
        transitionName={'Modal-anim'}
        transitionEnterTimeout={200}
        transitionLeaveTimeout={200}
      >
        <div className="Modal-overlay" onClick={close} />
        <div className="Modal">
          <p className="title">Modal Title</p>
          <div className="content">
            <p>
              Lorem, ipsum dolor sit amet consectetur adipisicing elit. Vel tempora nulla, non molestiae dicta ducimus. Et unde laborum eveniet ex quod doloribus quae, aliquam beatae atque, vero assumenda rem quo?
            </p>
          </div>
          <div className="button-wrap">
            <button onClick={close}>Confirm</button>
          </div>
        </div>
      </ReactTransitionGroup>
      :
      <ReactTransitionGroup transitionName={'Modal-anim'} transitionEnterTimeout={200} transitionLeaveTimeout={200} />
    </React.Fragment>
  )
}
export default Modal;

src/components/Modal/Modal.scss

.Modal-overlay{
  &.Modal-anim-enter {
    opacity: 0.00;
    transition: all 0.2s;
  }
  &.Modal-anim-enter.Modal-anim-enter-active {
    opacity: 1;
  }
  &.Modal-anim-leave {
    opacity: 1;
    transition: all 0.2s;
  }
  &.Modal-anim-leave.Modal-anim-leave-active {
    opacity: 0.00;
  }
}

.Modal{
  &.Modal-anim-enter {
    opacity: 0.00;
    transform: translate(-50%, -50%) scale(0.7);
    transition: all 0.2s;
  }
  &.Modal-anim-enter.Modal-anim-enter-active {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
  &.Modal-anim-leave {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    transition: all 0.2s;
  }  
  &.Modal-anim-leave.Modal-anim-leave-active {
    opacity: 0.00;
    transform: translate(-50%, -50%) scale(0.7);
  }
}

애니메이션 확인
GIF.gif

뒤로가기로 모달 닫기

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import App from './App';

ReactDOM.render(
  <BrowserRouter>
    <Route component={App} />
  </BrowserRouter>, document.getElementById('root'));

src/App.js

import React from 'react';
import Modal from './components/Modal';

class App extends React.Component{

  constructor(props){
    super(props);
    this.state = {
      isModalOpen: false, 
    }
  }

  componentDidUpdate(prevProps){
    if(this.state.isModalOpen && this.props.history.action === "POP") {
      this.setState({ isModalOpen: false }); 
    }
  }

  openModal = () => {
    this.props.history.push('/');
    this.setState({ isModalOpen: true });
  }

  closeModal = () => {
    this.props.history.goBack();
    this.setState({ isModalOpen: false }); 
  }

  render() {
    return (
    <main className="App">
      <button onClick={this.openModal}>Modal Open</button>
      <Modal isOpen={this.state.isModalOpen} close={this.closeModal} />
    </main>
    );
  }
}
export default App;

이제 모바일에서 뒤로가기 버튼으로 모달을 닫을 수 있습니다.