๋ฆฌ์•กํŠธ ํŒ์—…์ฐฝ/๋ชจ๋‹ฌ/๋‹ค์ด์–ผ๋กœ๊ทธ ๊ตฌํ˜„ํ•˜๊ธฐ, ์‚ญ์ œ๋ฒ„ํŠผ ๊ตฌํ˜„, ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น

    https://jaeseokim.dev/React/React-Portal_Render%EC%9D%98_%EC%B0%A8%EC%9D%B4%EC%A0%90_%ED%99%9C%EC%9A%A9%EB%B0%A9%EC%95%88_%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0/

     

    [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

     

     

     

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€