๋ฆฌ์กํธ ํ์ ์ฐฝ/๋ชจ๋ฌ/๋ค์ด์ผ๋ก๊ทธ ๊ตฌํํ๊ธฐ, ์ญ์ ๋ฒํผ ๊ตฌํ, ๊ตฌ์กฐ๋ถํดํ ๋น
[React] Portal, Render์ ์ฐจ์ด์ , ํ์ฉ๋ฐฉ์ ์์๋ณด๊ธฐ!
์ต๊ทผ Kakao Map Api๋ฅผ React Component ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๊ฐ๋ฐ์ ์งํํ๋ฉฐ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ReactDom์ Portal ๊ธฐ๋ฅ์ ๋ํด์ ๊ณต๋ถ๋ฅผ ํ๋ฉด์ Render์ ์ด๋ ํ ์ฐจ์ด์ ์ด ์๋์ง ๊ทธ๋ฆฌ๊ณ ํ์ฉ๋ฐฉ์์ ๋ํด์ ์ ๋ฆฌ ํด
jaeseokim.dev
Portalcreate๋ฅผ ์ด์ฉํ์ฌ ๊ตฌํ
๋๋ navbar ์์ ์๋ login button์ ๋๋ฅด๋ฉด ๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ์ํ ๋ชจ๋ฌ์ด ๋จ๋๋ก ๊ตฌํ์ด ํ์ํ๋ค.
Navbar๋ฅผ ๋ฐ๋ก ํ์ผ์ ์ชผ๊ฐ ๊ด๋ฆฌํ๊ณ ์๋ค.
Navbar.js
const [isShowing, setIsShowing] = useState(false);
const openModal = () =>
setIsShowing(true);
;
์๋ ๊ฒ isShowing์ด๋ผ๋ ๋ณ์๋ฅผ ๋ง๋ค์ด๋๊ณ ์ด๊ธฐ๊ฐ์ false์ธ ๋ชจ๋ฌ์ด ์ด๋ ค์์ง ์์ ์ํ๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ๋ค.
<h1 onClick={openModal} className="loginText">Login</h1>
<div>{isShowing ? <Login onClose={setIsShowing} /> : null}</div>
Login.js
import { createPortal } from "react-dom";
import { useState, useEffect } from "react";
import styled from "styled-components";
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import googleImage from '../assets/img/google.png';
import cancel from '../assets/img/cancel.png';
function Login(props) {
const { onClose } = props; //onClose๋ผ๋ ์ด๋ฆ์ผ๋ก setIsShowing ํจ์๋ฅผ ๊ฐ์ ธ์ด
const LoginBack=styled.div`
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
`;
const LoginModal=styled.div`
display: flex;
z-index: 100;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
top:calc(50% - 150px);
left:calc(50% - 215px);
width: 431px;
height: 305px;
background: #FFFFFF;
border-radius: 25px;
.cancelButton{
width: 12px;
height: 12px;
margin-left: 370px;
float: right;
margin-bottom: 27px;
}
.title{
font-size: 20px;
line-height: 23px;
color: #000000;
margin-bottom: 21px;
}
.desc{
font-weight: 400;
font-size: 16px;
line-height: 18px;
text-align: center;
color: #606060;
}
.google{
width: 359px;
height: 55px;
background: #FFFFFF;
border: 1px solid #606060;
border-radius: 11px;
font-weight: 400;
font-size: 18px;
line-height: 21px;
color: #000000;
display: flex;
gap: 20px;
align-items: center;
justify-content: center;
margin-top: 47px;
margin-bottom: 17px;
img{
width: 17px;
height: 17px;
}
}
.desc2{
font-size: 12px;
line-height: 14px;
color: #606060;
}
`
const onClick= () => {
console.log("clicked!");
};
return createPortal(
<LoginBack>
<LoginModal>
<img className="cancelButton" src={cancel} onClick={() => { onClose(false) }}></img>
<h1 className="title">Norithon์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค!</h1>
<p className="desc">๋ก๊ทธ์ธ์ ํตํด</p>
<p className="desc">๋ ์์ ๋กญ๊ฒ ์น์ฌ์ดํธ๋ฅผ ๋๋ฌ๋ณด์ธ์!</p>
<button onClick={onClick} className="google"><img src={googleImage}></img>Google ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ</button>
<p className="desc2">๋ก๊ทธ์ธ์ ์๋น์ค ์ด์ฉ์ฝ๊ด๊ณผ ๊ฐ์ธ์ ๋ณด ์ฒ๋ฆฌ๋ฐฉ์นจ์ ๋์ํ๊ฒ ๋ฉ๋๋ค. </p>
</LoginModal>
</LoginBack>,
document.getElementById("modal")
);
}
export default Login;
cancel ๋ฒํผ์ ๋๋ฅด๋ฉด Navbar.js์ ์๋ isShowing ๋ณ์ ๊ฐ์ ๋ฐ๊ฟ์ค์ผํ๋๋ฐ, ์ด๋ ๊ตฌ์กฐ๋ถํดํ ๋น์ ํตํด ํด๊ฒฐํ ์ ์์๋ค.
https://velog.io/@soral215/React.js-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%ED%95%A0%EB%8B%B9
[React.js] ๊ตฌ์กฐ ๋ถํด ํ ๋น
๊ตฌ์กฐ ๋ถํด ํ ๋น์ ES6์ ๋ฑ์ฅ๊ณผ ํจ๊ป ๊ตฌํ๋ ๋ฐฉ์์ด๋ค. ๋ฆฌ์กํธ์์ ๊ตฌ์กฐ ๋ถํด๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด ์์ ์๋ ํ๋ ๊ฐ์ ์ํ๋ ๋ณ์์ ๋์ ํ ์ ์๋ค. ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ด๊ณ ๊ฐ๋ตํ๋ฅผ ํ ๋ ์ ์ฉ
velog.io