React Modal

6301 ワード

reactモデルの実装

📌 /src/App.js

import { BrowserRouter, Routes, Route, } from 'react-router-dom';
import React from 'react';

function App() {
  return (
    <div className="App">
		...
        <div id="root-modal"></div>
        ...
    </div>
  );
}

export default App;
📌 /src/hooks/useModal.js

import React,{useState} from 'react'
import ModalPortal from '../Components/Modal/ModalPortal'

const useModal = ()=>{
  const [modalOpened , setModalOpened] = useState(false)

  const handleOpen = ()=>{
    setModalOpened(true)
  }

  const handleClose = ()=>{
    setModalOpened(false)
  }

  const ModalProvider = ({children})=>{
    return modalOpened && <ModalPortal closePortal={handleClose}>{children}</ModalPortal>
  }

  return [ModalProvider,handleOpen,handleClose]


}

export default useModal
📌 /src/Components/Modal/ModalPortal.js

import React, { useEffect, useRef, useState } from 'react'
import {createPortal} from 'react-dom'
import styled from 'styled-components'


const ModalPortal = ({children,closePortal}) => {
    const ref = useRef()
    const [mounted, setMounted] = useState(false)

    useEffect(()=>{
        setMounted(true)
        if(document){
            const dom = document.getElementById('root-modal')
            ref.current = dom
        }
    },[])

    if(ref.current && mounted){
        return createPortal(
            <Modal>
                <ModalBackground
                    role="presentation"
                    onClick={closePortal}
                />
                <ModalContent>
                    <ModalContentClose>
                      <button onClick={closePortal}>close</button>
                    </ModalContentClose>
                    <ModalContentMain>{children}</ModalContentMain>
                </ModalContent>
            </Modal>,
            ref.current
        )
    }
    return null
}

export default ModalPortal



const Modal = styled.div`
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 100%;
    height: 100%;
`

const ModalContent = styled.div`
    display: flex;
    align-items: center;
    flex-direction: column;
    z-index: 10;
    width: 300px;
    height: 300px;
    border: 1px solid;
    background: white;
`

const ModalContentClose = styled.div`
    display: inline-flex;
    justify-content: flex-end;
    width: 100%;
`

const ModalContentMain = styled.div`
    display: flex;
    padding: 1rem;
`
 const ModalBackground  = styled.div`
    position: absolute;
    width: 100%;
    height: 100%;
    background: black;
    opacity: 0.5;
 `