본문 바로가기

블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기

[81일차]20210707 웹팩, 리액트 header 반응형, router 라우터, 경일 홈페이지 상담게시판 page 구현

반응형

오늘 목표 : react, webpack 으로 components로 구성된 페이지 만들기

 

결과물

 

 

 

<준비 사항>

어제 만든 header 소스코드 까지 준비!

 

 

  반응형 main - 오른쪽의 햄버거를 X 로 만들기   

 

 

 

1. NavToggle Component 생성 및 button 대체 

 

Narbar.jsx 

react-icon에서 가져온 button 쪽, FaBars를 삭제하고 직접 만든 햄버거를 넣을 예정

 

코드가 길어질 것 같아서 component 로 만들어서 넣기 

 

아래처럼 import 해오고 그 다음에 NavToggle 파일 만들기 ! 

 

 

 

 

 

 

 

 

 

import React, { Component } from 'react'
import '../css/navbar.css'
import { FaFacebook, FaInstagram, FaBars, FaTwitter } from 'react-icons/fa'
import NavToggle from './NavToggle'    // 가져오기 


render() {
        return (
            <nav>
                <div className="nav-center">
                    {/*logo*/}
                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                        <NavToggle />
                        {/* <button className="nav-toggle">
                            <FaBars />
                        </button> */}
                    </div>
                    {/* navigation */}
                    <div className="links-container">
                        <ul className="links">
                            {

 

component  > NavToggle

import React, {Component} from 'react'

class NavToggle extends Component{
    render(){
        return;
    }
}

export default NavToggle

React가져오는 이유 : jsx 들은 React.createElement() 을 사용하기 때문 !  (안보이지만..) 

 

 

 

* label tag 클릭 <- 화면 보이고 안보이고를 구현할 때 사용할 예정

lable tag 안에 span  ㅡ x 3 개를 넣을 예정 (햄버거 구현) 

import React, {Component} from 'react'

class NavToggle extends Component{
    render(){
        return(
            <>
                <input type="checkbox" id="nav-toggle" className="nav-toggle"/>
                <label htmlFor = "nav-toggle">
                    {/* 클릭하면 nav-toggle id를 가진 아이를 바라봄  for 예약어 
                    그냥 쓸 수가 없어서 htmlFor로 써야함  jsx안에서 알아서 babel이 for로 바꿔서 랜더   */}
                    <span></span>
                    <span></span>
                    <span></span>
                </label>
            </>
        )
    }
}

export default NavToggle

=> npm ren dev  한번 코드 잘 작동되는지 쳌 

 

 

 

 

2. css 추가

import React, {Component} from 'react'
import '../css/NavToggle.css'

 

NavToggle css 

/* 체크박스 가리기 */
.nav-toggle{
    display:none;
}

/*  인접 접근자 
처음 선택한 바로 아래의 element ex) 아래 .nav-toggle + label 
label : inline이라 넓이 조절이 안되 -> block
어차피 얘를 flex로 관리할 거라 inline이 될것 
relative : 선을 하나하나 
*/

.nav-toggle + label{
    display:block;
    width:2.5rem;
    height:2rem;
    position:relative;
    cursor:pointer;
}


/* span 영역 설정  */
.nav-toggle + label > span{
    display: block;
    width:100%;
    height:5px;
    border-radius: 30px;
    background-color: black;
    transition: all .35s;
    position:absolute;
}

.nav-toggle + label > span:nth-child(1){
    top:0;
}
.nav-toggle + label > span:nth-child(2){}
.nav-toggle + label > span:nth-child(3){
    bottom:0;
}

 

 

 

mobile 바라보면서 pc를 바라보기  -- mobile을 만들면서 pc를 만드는게 더 편하다 ! 

 

 

 

 

3. 가운데의 선 내려보기 

nav-toggle.css 

.nav-toggle + label > span:nth-child(2){
    top:50%;
    transform: translateY(-50%);
}

-> 그냥 top:50%하면 가운데가 50%부터 ~ 들어가서 살짝 내려감 

transform: Y -50%을 해주면 완벽한 햄버거쓰

 

 

 

< 지금까지의 파일트리 >

 

 

 

 

4. nav-toggle - display: none을 해제하고 체크박스 쳌

-> 다시 display none 해주기 

 

 

 

 

5. input box 체크가 눌리면 모션을 다르게 주기 -> X 모양 만들기 

 

1) 먼저 막대기들을 가운데로 다 옮길 거야

.nav-toggle:checked + label > span:nth-child(1){
    top:50%;
    transform: translateY(-50%);
}
.nav-toggle:checked + label > span:nth-child(2){

}
.nav-toggle:checked + label > span:nth-child(3){
    bottom:50%;
    transform: translateY(50%);
}

-> 세개 막대기가 하나로 합쳐짐 

 

2) 각도만  바꿔주면됨 + 가운데를 없애기 ! 

.nav-toggle:checked + label > span:nth-child(1){
    top:50%;
    transform: translateY(-50%) rotate(45deg);
}
.nav-toggle:checked + label > span:nth-child(2){
    opacity:0;
}
.nav-toggle:checked + label > span:nth-child(3){
    bottom:50%;
    transform: translateY(50%) rotate(-45deg);
}

 

 

 

여기까지 모바일 버전 ! 

 

 

 

 

6. PC 버전 어떻게 할지 정하기 

/* pc 버전  */

@media screen and (min-width:800px){
    .nav-toggle + label{
        display: none;
    }
}

pc 버전일 경우 없애기 ! 

 

 

NavToggle.css 전체 코드 

/* 체크박스 가리기 */
.nav-toggle{
    display:none;
}

/*  인접 접근자 
처음 선택한 바로 아래의 element ex) 아래 .nav-toggle + label 
label : inline이라 넓이 조절이 안되 -> block
어차피 얘를 flex로 관리할 거라 inline이 될것 
relative : 선을 하나하나 
*/

.nav-toggle + label{
    display:block;
    width:2.5rem;
    height:2rem;
    position:relative;
    cursor:pointer;
}


/* span 영역 설정  */
.nav-toggle + label > span{
    display: block;
    width:100%;
    height:5px;
    border-radius: 30px;
    background-color: black;
    transition: all .35s;
    position:absolute;
}

.nav-toggle + label > span:nth-child(1){
    top:0;
}
.nav-toggle + label > span:nth-child(2){
    top:50%;
    transform: translateY(-50%);
}
.nav-toggle + label > span:nth-child(3){
    bottom:0;
}


/* checked 임을 나타내는 css 선택자 : 
.nav_toggle:checked~

*/


.nav-toggle:checked + label > span:nth-child(1){
    top:50%;
    transform: translateY(-50%) rotate(45deg);
}
.nav-toggle:checked + label > span:nth-child(2){
    opacity:0;
}
.nav-toggle:checked + label > span:nth-child(3){
    bottom:50%;
    transform: translateY(50%) rotate(-45deg);
}


/* pc 버전  */

@media screen and (min-width:800px){
    .nav-toggle + label{
        display: none;
    }
}

 

 

 

 


 

 

 

 

  NavBar CSS 하기  

 

요거때문에 pc 버전때 안보이게 가능했었음 

 

 

Navbar.css

 

 

Navbar component 안에서 상태값 관리하기 

Navbar.jsx

                url:'/',
                text:'coconut'
            },
            {
                id:2,
                url:'/',
                text:'banana'
            },
            {
                id:3,
                url:'/',
                text:'mango'
            }
        ],
        showLinks:false,
    }

false : 안보이게  : links-contatiner 

true :  100% (보이게) : links-container on 

 

                    {/* navigation */}
                    <div className="links-container">
                        <ul className="links">
                            {

위의 className에 on이라는 class 붙여서 on and off 구현 

 

 

Narvar.css

/* rem 확대 축소 비율로 늘어남 */ 
/* .links-container의 높이값이 생기면 내용 출력할 수 있다. */ 
.links-container{
    
    height:0;
    overflow:hidden;
}

.links-container.on{
    height:100%;
}

 

 

Navbar.jsx

아래처럼 할 수 있지만 더 함수로 밖으로 빼주기 

                    {/* navigation */}
                    <div className={this.state.showLinks ? 'links-container' : 'links-container on'}>
                        <ul className="links">
                            {

↓↓↓↓↓↓↓↓↓↓↓

    showContainer = ()=>{             // 요로코롬
        let className = this.state.showLinks ? 'links-container on' : 'links-container'
        return className
    }
    
    render() {
        return (
            <nav>
                <div className="nav-center">
                    {/*logo*/}
                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                        <NavToggle />
                        {/* <button className="nav-toggle">
                            <FaBars />
                        </button> */}
                    </div>
                    {/* navigation */}
                    <div className={this.showContainer()}>   //return 값 받아야하니 () 추가 
                        <ul className="links">
                            {

이제 클릭했을 때 상태값을 반대로 만들기 

함수 하나 더 만들기 -> NavToggle Component에 해당 함수 보내기  named toggle

    handleToggle=()=>{
        this.setState({showLinks:!this.state.showLinks})
    }

    render() {
        return (
            <nav>
                <div className="nav-center">
                    {/*logo*/}
                    <div className="nav-header">
                        <h1 className="logo">Logo</h1>
                        <NavToggle 
                            toggle={this.handleToggle}
                        />
                    </div>

 

NavToggle에 있는 아이을 클릭했을 때 

 

NavToggle.jsx

import React, {Component} from 'react'
import '../css/NavToggle.css'

class NavToggle extends Component{
    render(){
        return(
            <>
                <input 
                    type="checkbox" 
                    id="nav-toggle" 
                    className="nav-toggle" 
                    onClick={()=>this.props.toggle()}   // 함수형
                />

onClick 이 발생될 떄 (==   ()=> arrow 함수가 실행이 될 때 )this.props.toggle() 함수가 실행되도록 하기 위해

근데 this.props.toggle() 도 가능 ~ 

 

this.props.toggle   OK
this.props.toggle()  NOPE
()=>{this.props.toggle()}   OK

 

 

Navbar.css추가 아래 PC, mobile 버전

    /* MOBILE */ 
    .links{
        display: flex;
        flex-direction: column;
        align-items:center;
        box-sizing: border-box;
    }
    
    .links>li{
        width:100%;
        text-align: center;
        border-bottom: 1px solid #eee
        ;
    }

    .links>li>a{
        display:inline-block;
        /* margin:0 0.5rem; */
        color:#000;
        font-size: 1.25rem;
        padding:0.75rem;
        
    }

        /*  PC */ 
        .links{
            display: flex;
            flex-direction: row;
        }
        
        .links>li{
            width:100%;
            text-align: center;
            border-bottom: none;
        }
    
        .links>li>a{
            margin:0 0.5rem;
            color:#000;
            font-size: 1.25rem;
        }

 

css 전체

/* mobile */

.nav-header{
    display:flex;
    align-items: center;
    justify-content: space-between; /* 양쪽 끝 */
    padding:1rem;
}


.logo{
    font-size: 3rem;
}

/* rem 확대 축소 비율로 늘어남 */ 
/* .links-container의 높이값이 생기면 내용 출력할 수 있다. */ 
.links-container{
    
    height:0;
    overflow:hidden;
}

.links-container.on{
    height:100%;
}

.social-icons{
    height:0;
    overflow:hidden;
}

.nav-toggle{
    font-size:3rem;
    /*투명하게 만들기 */
    background:transparent;
    border-color:transparent;
    color:blue;
}



    /* MOBILE */ 
    .links{
        display: flex;
        flex-direction: column;
        align-items:center;
        box-sizing: border-box;
    }
    
    .links>li{
        width:100%;
        text-align: center;
        border-bottom: 1px solid #eee;
    }

    .links>li>a{
        display:inline-block;
        color:#000;
        font-size: 1.25rem;
        padding:0.75rem;
    }

/* PC css style */
@media screen and (min-width:800px){


    .logo{
        font-size: 4rem;
    }

    .nav-toggle{
        /*pc 경우에 토글 안보이게*/ 
        font-size: 0px;
        color:blue;
    }

    .nav-center{
        max-width:1170px;
        margin:0 auto;
        display: flex;
        align-items:center;
        justify-content: space-between;
        padding:1rem;
    }

    .links-container{
        height:auto;
    }



        /*  PC */ 
    .links{
        display: flex;
        flex-direction: row;
    }
        
    .links>li{
        width:100%;
        text-align: center;
        border-bottom: none;
    }
   
    .links>li>a{
        margin:0 0.5rem;
        color:#000;
        font-size: 1.25rem;
    }




    .social-icons{
        display:flex;
        height:auto;
    }

    .social-icons>li>a{
        margin: 0 .5rem;
        color: red;
    }

}

PC
Mobile

 

 

 


 

 

React 

Single Page Application 

링크 이동해도 페이지는 바뀌지 않음 

그래서 왠만해서는 a tag 를 넣지않음 ! 넣더라도 link 개념을 빼고 씀

JS 에서는 url 관리해주는 매서드가 존재하는데 url 값을 js 가 바꾸기는 하지만 link 이동 (요청 to server) 은 하지 않음. 

==> a hreg="j~: void(0)" -> url은 바뀜 / 요청은 안함 

요걸 이용해서 ----> url 을 바뀐걸로 component를 설정해주는 것 ---> react 라우터 

 

JS 로 했을 때는 header 메뉴를 클릭했을 때 server 로 url 요청 -- 브라우저에 다시 그림 

react - home 이라는 것을 쓰면 url 에 home 이 있으면 아래에 home Component를 보여줌  !

 

이제 react router 배우기 ! 

 

Next   == React 

CRA 는 왠만하면 안쓴다 Next라는 좋은게 있어서 ! - server side rendering 

NEXT도 배울 예정 

 

Express 기준으로  url 이 바뀌었을 때는 page 전체를 reload (html 처음부터 닫는 끝-까지를 ) 다시 그려줌. 

React는.. 못들었다. 아마 부분부분 바꿔주는... ?

 

 

 

 

   라우터 설치하기   

 

1. 아래 명령어 실행 / 설치 

$ npm i react-router-dom

 

 

2. App.jsx (최상위 Component) 

항상 라우터는 최상위 노드에서 작업을 해야함 ! ★

 

import React, {Component} from 'react'
import Navbar from './component/Navbar'
import {BrowserRouter, Route, Switch} from 'react-router-dom'

class App extends Component{
    render(){
        return(
            <>
                <BrowserRouter>
                    <Navbar />
                    {/* 여기서부터 내용 보이는 영역(header 아래) */}
                    <Switch>
                        <Route path="" component="" />
                    </Switch>
                </BrowserRouter>
            </>
        )
    }
}

export default App

Navebar 아래 영역은 가변적 -> Switch 

 

path="" url 값이 어떤 거일 때  component ="실행할 Component" <-요걸 불러오겠다.

exact = > 정확한 저 path 값이 들어올 때 compont 를 실행하겠다. 

 

 

webpack - pages - 각각의 jsx Component 만들기 

Coconut.jsx

import React, {Component} from 'react'

class Coconut extends Component{
    render(){
        return(
            <>
                hi I am Coconut 
            </>
        )
    }
}

export default Coconut

Banana.jsx / Mango.jsx 도 위와 같이 ! 

 

 

 

App.jsx 에 위의 Components 가져오기  &  사용하기 

import React, {Component} from 'react'
import Navbar from './component/Navbar'
import {BrowserRouter, Route, Switch} from 'react-router-dom'
import Coconut from './pages/Coconut'
import Banana from './pages/Banana'
import Mango from './pages/Mango'

class App extends Component{
    render(){
        return(
            <>
                <BrowserRouter>
                    <Navbar />
                    {/* 여기서부터 내용 보이는 영역(header 아래) */}
                    <Switch>
                        <Route exact path="/" component={Coconut} />
                        <Route exact  path="/banana" component={Banana} />
                        <Route exact  path="/mango" component={Mango} />
                    </Switch>
                </BrowserRouter>
            </>
        )
    }
}

export default App

Navbar .jsx

        menu: [
            {
                id:1,
                url:'/',
                text:'coconut'
            },
            {
                id:2,
                url:'/banana',
                text:'banana'
            },
            {
                id:3,
                url:'/mango',
                text:'mango'
            }
        ],
        showLinks:false,
    }

link 를 이동하지 않도록 위의 오류 안나게 만들기 

 

 

Navbar.jsx

import React, { Component } from 'react'
import '../css/navbar.css'
import { FaFacebook, FaInstagram, FaBars, FaTwitter } from 'react-icons/fa'
import NavToggle from './NavToggle'
import {Link} from 'react-router-dom'

class Navbar extends Component {
    state = {
        social: [
            {
                id: 1,

Link Component를 a tag 대체로 쓸것 

또 a 는 Link Component로 쓰고 href -> a로 바꾸기 

                    {/* navigation */}
                    <div className={this.showContainer()}>
                        <ul className="links">
                            {
                                this.state.menu.map(item=>{
                                    let {id, url, text} = item
                                    return(
                                        <li key={id}>
                                            <Link to={url}>{text}</Link>
                                        </li>
                                    )
                                })

요렇게 클릭하는대로 나온다 ! 

 

 

 

 

Coconut.jsx

import React, { Component } from 'react'
import '../css/Coconut.css'

class Coconut extends Component {
    render() {
        return (
            <>
                <div>
                    <span className="coconut">
                        hi I am Coconut
                    </span>
                </div>
            </>
        )
    }
}

export default Coconut

 

Coconut.css

.coconut{
    /* display: block; */
    background-color: blueviolet;
    color:#fff
}

.coconut{
    display: block;
    height:100px;
    background-color: blueviolet;
    color:#fff
}

 

 

* url 오류 계속 났을 때 아래 true로 바꿔주면 괜찮다  !

 

 

 

 

 

 

과제 : 경일게임아카데미 아래 페이지 react로 만들기 ! 

banana menu page에서 내가 사용할 component는 총 3개로 정했다. top, sidebar, content 

 

 

기본틀 만들기

 

내용 넣기

배경 색 지우기

 

 

지우니깐 예뿌다  

 

 

반응형