๐ช React JS์์ ์ฌ์ฉ์ ์ง์ ๋ชจ๋ฌ/ํ์ ๊ตฌ์ฑ ์์ ๊ตฌ์ถ
22542 ๋จ์ด javascriptbeginnerscssreact
์๋์ ๊ฐ์ด ์งํํ ์์ ์ ๋๋ค.
์ ์ ํ ๋ฐ์ ์ฑ ๋ง๋ค๊ธฐ
๋จผ์ ๋ค์ ๋ช
๋ น์ ์ฌ์ฉํ์ฌ create-react-app
cli ๋๊ตฌ์ ๋์์ผ๋ก ์๋ก์ด ๋ฐ์ ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค.
npx create-react-app modal
npm start
๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ ์ฑ์ ์์ํ๊ณ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด๊ณ http://localhost:3000
๋ก ์ด๋ํฉ๋๋ค. ๋ฐ์์ ๊ธฐ๋ณธ ์ฑ์ด ํ์๋ฉ๋๋ค.
์ด์ ์ค์ Modal ๊ตฌ์ฑ ์์๋ฅผ ๋์์ธํ๊ณ ๋ง๋๋ ๋ค์ ๋จ๊ณ๋ก ๋์ด ๊ฐ์๋ค.
Modal ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ ๋ฐ ๋์์ธ
์ด์ ์ฑ์ src ํด๋ ์์ ๊ตฌ์ฑ ์์ ํด๋๋ฅผ ๋ง๋ญ๋๋ค. ์ด ๊ตฌ์ฑ ์์ ํด๋ ์์ ๋ชจ๋ฌ ๊ตฌ์ฑ ์์๋ฅผ ํฌํจํ๋ ํ์ผModal.js
๊ณผ ๋ชจ๋ฌ ๊ตฌ์ฑ ์์์ ๋ํ css ์คํ์ผ์ ํฌํจํ๋ ํ์ผmodal.module.css
์ด ์๋ ๋ชจ๋ฌ ํด๋๋ฅผ ๋ง๋ญ๋๋ค.
๋์์ธ ๋ถ๋ถ์ผ๋ก ๋์๊ฐ์ ์๋์ ์ฝ๋ ์ค๋ํซ์ด ์์ต๋๋ค.
/* modal.module.css */
.modal__wrap {
position: fixed;
display: block;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 auto;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
overflow-x: hidden;
background-color: rgba(31, 32, 41, .75);
pointer-events: none;
opacity: 0;
transition: opacity 250ms 700ms ease;
}
.visible {
pointer-events: auto;
opacity: 1;
transition: all 300ms ease-in-out;
}
.modal {
overflow-y: scroll;
overflow-x: hidden;
position: relative;
display: block;
width: 60vw;
height: 60%;
min-height: 400px;
min-width: 400px;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 20px;
border-radius: 4px;
padding-bottom: 20px;
background-color: #fff;
align-self: center;
box-shadow: 0 12px 25px 0 rgba(199, 175, 189, .25);
opacity: 0;
transform: scale(0.6);
transition: opacity 250ms 250ms ease, transform 300ms 250ms ease;
transform: scale(0);
}
.visible .modal {
opacity: 1;
transform: scale(1);
transition: opacity 250ms 500ms ease, transform 350ms 500ms ease;
}
npx create-react-app modal
์ด์ ์ฑ์ src ํด๋ ์์ ๊ตฌ์ฑ ์์ ํด๋๋ฅผ ๋ง๋ญ๋๋ค. ์ด ๊ตฌ์ฑ ์์ ํด๋ ์์ ๋ชจ๋ฌ ๊ตฌ์ฑ ์์๋ฅผ ํฌํจํ๋ ํ์ผ
Modal.js
๊ณผ ๋ชจ๋ฌ ๊ตฌ์ฑ ์์์ ๋ํ css ์คํ์ผ์ ํฌํจํ๋ ํ์ผmodal.module.css
์ด ์๋ ๋ชจ๋ฌ ํด๋๋ฅผ ๋ง๋ญ๋๋ค.๋์์ธ ๋ถ๋ถ์ผ๋ก ๋์๊ฐ์ ์๋์ ์ฝ๋ ์ค๋ํซ์ด ์์ต๋๋ค.
/* modal.module.css */
.modal__wrap {
position: fixed;
display: block;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 auto;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
overflow-x: hidden;
background-color: rgba(31, 32, 41, .75);
pointer-events: none;
opacity: 0;
transition: opacity 250ms 700ms ease;
}
.visible {
pointer-events: auto;
opacity: 1;
transition: all 300ms ease-in-out;
}
.modal {
overflow-y: scroll;
overflow-x: hidden;
position: relative;
display: block;
width: 60vw;
height: 60%;
min-height: 400px;
min-width: 400px;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 20px;
border-radius: 4px;
padding-bottom: 20px;
background-color: #fff;
align-self: center;
box-shadow: 0 12px 25px 0 rgba(199, 175, 189, .25);
opacity: 0;
transform: scale(0.6);
transition: opacity 250ms 250ms ease, transform 300ms 250ms ease;
transform: scale(0);
}
.visible .modal {
opacity: 1;
transform: scale(1);
transition: opacity 250ms 500ms ease, transform 350ms 500ms ease;
}
.modal__wrap
๋ ๋ชจ๋ฌ์ ๋ํผ ๋ฐ ๋ฐฐ๊ฒฝ์ ๋ํ ์คํ์ผ์ ์ง์ ํ๋ ํด๋์ค์
๋๋ค. .modal
๋ ์ด๊ธฐ์ ์จ๊ฒจ์ง ์ค์ ๋ชจ๋ฌ ๊ตฌ์ฑ ์์์ ์คํ์ผ์ ๊ฐ์ง ํด๋์ค์
๋๋ค. .visible
ํด๋์ค๋ ๋ชจ๋ฌ์ด ํ์ด๋ ์ธ ๋ฐ ํ์ด๋ ์์ ํจ๊ณผ์ ํจ๊ป ํ์๋๋๋ก ํฉ๋๋ค. ์ด์ Modal ์ปดํฌ๋ํธ๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
์๋๋ ์ด์ ๋ํ ์ฝ๋ ์ค๋ํซ์ ๋๋ค.
//Modal.js
import React, { useEffect, useRef } from 'react';
import Button from '../button/Button';
import CloseIcon from '../CloseIcon';
import styles from './modal.module.css';
const Modal = ({ modalStyle, children, show, onClose, backdropStyle }) => {
const modalRef = useRef(null);
useEffect(
() => {
if (show) {
modalRef.current.classList.add(styles.visible);
}
else {
modalRef.current.classList.remove(styles.visible);
}
},
[
show
]
);
return (
<React.Fragment>
<div ref={modalRef} style={backdropStyle} className={`${styles.modal__wrap}`}>
<Button
onClick={onClose}
style={{ width: 60, height: 40, position: 'absolute', top: 0, right: 0, margin: '1rem' }}
className={styles.close__btn}
>
<CloseIcon height="20px" width="20px" className={styles.close__icon} />
</Button>
<div style={modalStyle} className={styles.modal}>
{children}
</div>
</div>
</React.Fragment>
);
};
export default Modal;
์ด ๊ตฌ์ฑ ์์๋ ๋ค ๊ฐ์ง ์ํ์ ์ฌ์ฉํฉ๋๋ค.
1.
modalStyle
- ํ์๋๋ ๋ชจ๋ฌ ์ฐฝ์ ์คํ์ผ์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค.backdropStyle
- ๋ชจ๋ฌ ์ฐฝ์ ๋ฐฐ๊ฒฝ ์คํ์ผ์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค. onClose
- ๋ชจ๋ฌ์ ๋ซ๋ ๋
ผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ. show
- ๋ชจ๋ฌ์ด ์ด๋ ค ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ๋ถ์ธ ์์ฑ์
๋๋ค. ์ฌ๊ธฐ์์ ์ด ๊ตฌ์ฑ ์์ ๋ด๋ถ์ ๋ ๊ฐ์ ๊ตฌ์ฑ ์์Button์ CloseIcon์ ๋ ์ฌ์ฉํ์ต๋๋ค. Now Button ๊ตฌ์ฑ ์์๋ ๊ธฐ๋ณธ ์คํ์ผ์ ๊ฐ๋จํ ๋ฒํผ์ ๋๋ค. CloseIcon์ ๋จ์ํ ๋ชจ๋ฌ์ ๋ซ๋ ์์ด์ฝ
svg
์
๋๋ค.์ด ๊ตฌ์ฑ ์์์๋ ๋ ๊ฐ์ง ์ฃผ์ ๊ธฐ๋ฅ ๋ถ๋ถ์ด ์์ต๋๋ค.
useEffect()
ํํฌ ๋ด๋ถ์์ show prop์ด ์ฐธ์ธ์ง ์๋์ง ํ์ธํฉ๋๋ค. show๊ฐ true ์ธ ๊ฒฝ์ฐ ๊ตฌ์ฑ ์์์ .visible
ํด๋์ค๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ .visible
react hook์ ๋์์ผ๋ก Modal ๊ตฌ์ฑ ์์์์ useRef()
ํด๋์ค๋ฅผ ์ ๊ฑฐํฉ๋๋ค. onClose()
๋ฅผ CloseIcon ์ onClick
์ด๋ฒคํธ ์ฒ๋ฆฌ๊ธฐ์ ์ถ๊ฐํ์ฌ ํด๋ฆญ ์ ๋ชจ๋ฌ์ด ๋ซํ๋๋ก ํฉ๋๋ค. ๋ชจ๋ฌ์ ํ์ํ๋ ์ด๋ฒคํธ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋ ๋ฒํผ
๊ฐ๋จํ ํ๊ธฐ ์ํด ์๋์ ๊ฐ์ด App.js ํ์ผ์ Button์ ์ถ๊ฐํ์ต๋๋ค.
//App.js
import React, { useState } from 'react';
import './App.css';
import Button from './components/button/Button';
import Modal from './components/modal/Modal';
function App() {
const [
show,
setShow
] = useState(false);
return (
<React.Fragment>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<Button onClick={() => setShow(true)}>Open Modal</Button>
</div>
<Modal show={show} onClose={() => setShow(false)}>
<div className="content">
<img src="https://cdn.pixabay.com/photo/2015/01/09/11/11/office-594132__340.jpg" alt="Developer" />
<div className="text">
<h2>John Doe</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe aliquid placeat omnis
adipisci dolores quae amet mollitia sint, temporibus eum magnam facilis odio ex incidunt?
Deleniti quam et rem obcaecati. Laborum atque odit expedita nulla.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Expedita labore laborum, assumenda
dolorum provident quod itaque earum, officia in placeat dignissimos nostrum? Totam corrupti
nihil repudiandae ducimus atque quod eos!
</p>
</div>
</div>
</Modal>
</React.Fragment>
);
}
export default App;
๊ทธ๊ฒ ๋น์ ์ด ํ ์ผ์
๋๋ค. ๊ทธ๋งํผ ๊ฐ๋จํฉ๋๋ค. ์ด์ ํ๋ก์ ํธ ์ด๋์์๋ ์ด ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด์ ๊ฐ์ ๋ ๋ง์ ๊ธฐ์ฌ๋ฅผ ๋ณด๋ ค๋ฉด ๋ด ๊ฐ์ธ ๋ธ๋ก๊ทธhere๋ฅผ ํ์ธํ์ญ์์ค.
Modal ์ปดํฌ๋ํธ์ CodeSandbox ๋งํฌ์
๋๋ค.
์ด ํํ ๋ฆฌ์ผ์ด ์ฌ๋ฌ๋ถ์๊ฒ ๋์์ด ๋์๋์ง, ์ด๋ค ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋์ง ์๋ ค์ฃผ์ธ์. ํญ์ ์ฝ์ด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!!!
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ช React JS์์ ์ฌ์ฉ์ ์ง์ ๋ชจ๋ฌ/ํ์
๊ตฌ์ฑ ์์ ๊ตฌ์ถ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค
https://dev.to/satishnaikawadi2001/build-custom-modal-popup-component-in-react-js-29g5
ํ
์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ
์ธ ๋ฐ๊ฒฌ์ ์ ๋
(Collection and Share based on the CC Protocol.)
//App.js
import React, { useState } from 'react';
import './App.css';
import Button from './components/button/Button';
import Modal from './components/modal/Modal';
function App() {
const [
show,
setShow
] = useState(false);
return (
<React.Fragment>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<Button onClick={() => setShow(true)}>Open Modal</Button>
</div>
<Modal show={show} onClose={() => setShow(false)}>
<div className="content">
<img src="https://cdn.pixabay.com/photo/2015/01/09/11/11/office-594132__340.jpg" alt="Developer" />
<div className="text">
<h2>John Doe</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe aliquid placeat omnis
adipisci dolores quae amet mollitia sint, temporibus eum magnam facilis odio ex incidunt?
Deleniti quam et rem obcaecati. Laborum atque odit expedita nulla.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Expedita labore laborum, assumenda
dolorum provident quod itaque earum, officia in placeat dignissimos nostrum? Totam corrupti
nihil repudiandae ducimus atque quod eos!
</p>
</div>
</div>
</Modal>
</React.Fragment>
);
}
export default App;
Reference
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ช React JS์์ ์ฌ์ฉ์ ์ง์ ๋ชจ๋ฌ/ํ์ ๊ตฌ์ฑ ์์ ๊ตฌ์ถ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://dev.to/satishnaikawadi2001/build-custom-modal-popup-component-in-react-js-29g5ํ ์คํธ๋ฅผ ์์ ๋กญ๊ฒ ๊ณต์ ํ๊ฑฐ๋ ๋ณต์ฌํ ์ ์์ต๋๋ค.ํ์ง๋ง ์ด ๋ฌธ์์ URL์ ์ฐธ์กฐ URL๋ก ๋จ๊ฒจ ๋์ญ์์ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค