티스토리 뷰

새로운 프로젝트 생성 & Bootstrap 사용하기


- Bootstrap 라이브러리: 레이아웃을 복사붙여넣기 식으로 편하게 개발가능함 (라이브러리 홈 들어가서 설치하면 됨)

 

설치 후 react-bootstrap 사이트에서 UI 복사 붙여넣기 가능

ex. button 검색 후 코드 복붙하기

 

- Navbar

import {Navbar, Container, Nav} from 'react-bootstrap'; // 상단에 import 적고
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';


function App() {
  return (
    <div className="App">
      
      <Navbar bg="dark" variant="dark"> // 코드 복붙하기
        <Container>
          <Navbar.Brand href="#home">Navbar</Navbar.Brand>
          <Nav className="me-auto">
            <Nav.Link href="#home">Home</Nav.Link>
            <Nav.Link href="#features">Features</Nav.Link>
            <Nav.Link href="#pricing">Pricing</Nav.Link>
          </Nav>
        </Container>
      </Navbar>
    </div>
  );
}

export default App;

 

커스텀하고 싶으면 clasName적은 뒤 css에서 만들면 됨.

 

 

 

 

이미지 넣는 법 & public 폴더 이용하기


- css 파일에서 src 폴더안에 있는 사진 쓰고 싶을 때 './이미지경로' 쓰면 됨

(App.css)

.main-bg {
  height : 300px;
  background-image : url('./bg.png');
  background-size : cover;
  background-position : center;
}

// src안에있는 img 파일을 쓰고 싶을 때는
// background-image: url('./img/캡1.PNG'); 이렇게 쓰면 됨

 

 

- html 안에서 src 폴더의 이미지를 넣고 싶으면 이미지를 import 해오고 사용해야함

import bg from './bg.png'

function App(){
  return (
    <div>
      <div className="main-bg" style={{ backgroundImage : 'url(' + bg + ')' }}></div>
    </div>
  )
}

 

1. import 작명 from './이미지경로' 한 다음에

2. 이미지경로가 필요한 곳에서 작명한걸 사용하면 됨

<img>태그 쓰고싶으면 <img src={bg}/> 이렇게 써도 보임. 귀찮으면 css파일을 활용하기

 

 

 

-public 폴더의 용도 

여러가지 소스코드는 src 폴더에 보관하면 되는데 이미지같은 static 파일의 경우 public 폴더에 보관해도 됨

 

- 이유?

리액트로 개발을 끝내면 build 작업이라는걸 하는데 지금까지 짰던 코드를 한 파일로 압축해주는 작업임.

src 폴더에 있던 코드와 파일은 다 압축이 되는데 public 폴더에 있는 것들은 그대로 보존해줌.

그래서 형태를 보존하고 싶은 파일은 public 폴더에 넣으면 되는데 js 파일은 그럴 일은 거의 없고 이미지, txt, json 등 수정이 필요없는 static 파일들의 경우엔 public 폴더에 보관해도 상관없음.

 

 

-public 폴더에 있는 이미지 사용할 땐

<img src="/logo192.png" />

그냥 /이미지경로 사용하면 됨. 그래서 페이지에 이미지 100장을 넣어야하는 경우 public 폴더에 밀어넣으면 import 100번 안해도 되니 편리하다. css 파일에서도 ./이미지경로 사용하면 된다.

 

 

하지만 권장되는 방식은 다음과 같다.

<img src={process.env.PUBLIC_URL + '/logo192.png'} />

 

왜냐면 리액트로 만든 html 페이지를 배포할 때 codingapple.com 경로에 배포하면 아무런 문제가 없지만codingapple.com/어쩌구/ 경로에 배포하면 /logo192.png 이렇게 쓰면 파일을 찾을 수 없다고 나올 수도 있기 때이다. 

그래서 /어쩌구/ 를 뜻하는 process.env.PUBLIC_URL 이것도 더해주면 된다고 한다.

 

codingapple.com/어쩌구/ 경로에 리액트로 만든 페이지를 배포할 일이 아예 없으면 굳이 안해도 된된다. 

 

 

 

 

저번시간 숙제 해설 (Card 컴포넌트 만들기)


- 문자 중간 변수넣기 문법

function Card(props) {
  return (
    <Col>
      <img src={'https://codingapple1.github.io/shop/shoes' + (props.i+1) + '.jpg'} width="80%" />
      <h4>{props.shoes.title}</h4>
      <p>{props.shoes.price}</p>
    </Col>
  )
}

 

 

 

 

리액트 라우터 1 : 셋팅이랑 기본 라우팅


-페이지 나누는 법 (리액트 사용)

1. 컴포넌트 만들어서 상세페이지 내용 채움

2. 누가 /detail 접속하면 그 컴포넌트 보여줌

 

react-router-dom 라이브러리 쓰면 그런거 쉽게 만들 수 있음.

 

 

 

- 내가 만든 js 파일들은 ./ 부터 시작하고 ./가 없는 것들은 대부분 설치한 라이브러리임

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals'; // 내가 만든 것
import { BrowserRouter } from 'react-router-dom'; // 설치한 것

 

 

-라우터로 페이지 나누는 법 

다른 웹사이트를 잘 살펴보면 codingapple.com/어쩌구로 접속하면 A페이지를 보여주고  codingapple.com/저쩌구로 접속하면 B페이지를 보여준다.  이런 식으로 url 경로마다 다른 페이지를 보여주고 싶으면 이렇게 작성한한다.

(App.js)

import { Routes, Route, Link } from 'react-router-dom'

function App(){
  return (
    (생략)
    <Routes>
      <Route path="/detail" element={ <div>상세페이지임</div> } />
      <Route path="/about" element={ <div>어바웃페이지임</div> } />
    </Routes>
  )
}

1. 우선 상단에서 여러가지 컴포넌트를 import 해오고

2. <Routes> 만들고 그 안에 <Route>를 작성합니다.

3. <Route path="/url경로" element={ <보여줄html> } /> 이렇게 작성하면 됩니다. 

 

 

 

 

* import, export 까먹지 말기!

function Detail() {
    return (
      <div className="container">
        <div className="row">
          <div className="col-md-6">
            <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
          </div>
          <div className="col-md-6">
            <h4 className="pt-5">상품명</h4>
            <p>상품설명</p>
            <p>120000원</p>
            <button className="btn btn-danger">주문하기</button> 
          </div>
        </div>
      </div> 
    )
  }

  export default Detail;

 

 

 

- 리액트 Hook

- useNavigate(): 페이지 이동을 도와주는 함수

 

- link와의 차이

  • 클릭 시 바로 이동하는 로직 구현 시에 사용
  • ex) 상품 리스트에서 상세 페이지 이동 시

 

2. useNavigate

  • 페이지 전환 시 추가로 처리해야 하는 로직이 있을 경우 useNavigate 사용
  • ex) 로그인 버튼 클릭 시
    • 회원가입 되어 있는 사용자 -> Main 페이지로 이동
    • 회원가입이 되어 있지 않은 사용자 -> SignUp 페이지로 이동

 

<Navbar className="navBar">
        <Container>
          <Navbar.Brand href="#home" className='brandLink'>WelDog</Navbar.Brand>
          <Nav className="me-auto">
          <Link onClick={()=>{ navigate('/') }} to="/" className='homeLink'>홈</Link>
          <Link onClick={()=>{ navigate('/detail') }} to="/detail" className='detailLink'>Detail</Link>
          </Nav>
        </Container>
</Navbar>

 

 

 

- src 폴더 안에 Detail을 넣음

import {Navbar, Container, Nav, Row} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import 캡1 from './img/캡1.PNG'
import Col from 'react-bootstrap/Col';
import { useState } from 'react';
import data from './data.js';
import { Routes, Route, Link } from 'react-router-dom'
import Detail from './routes/Detail.js' // src 폴더 안에 Detail을 넣음

 

 

 

- 404 페이지

<Route path="*" element={<div>404</div>} />

 

 

- nested routes

예제) about 페이지 않에 member와 location이 있는 페이지를 만들고 싶을 때

방법1)
<Route path="/about" element={<About />}>
  <Route path="member" element={<About />} />
  <Route path="location" element={<About />} />
</Route>

방법2) nested routes
<Route path="/about/member" element={<About />} />
<Route path="/about/location" element={<About />} />

- nested routes로 작성할 때 장점

1. route 작성이 약간 간단해질 수 있음

2. 접속시 element 2개나 보임

예제)

<Route path="/about" element={<About />}>
  <Route path="member" element={<div>멤버임</div>} />
  <Route path="location" element={<div>위치정보임</div>} />
</Route>

function About() {
  return (
    <div>
      <h4>회사정보임</h4>
      <Outlet></Outlet>
    </div>
  )
}

회사정보임 아래에 멤버임 or 위치정보임이 뜸 ( 2개의 문장이 같이 보임)

 

 

3. 뒤로가기 버튼 이용가능

4. 페이지 내 이동이 쉬움(UI 스위치 조작 쉬움)

 

-nested routes언제 씀?

여러 유사한 페이지 필요할 때.

 

 

 

리액트 라우터 3 : URL 파라미터로 상세페이지 100개 만들기


<Route path="/detail/:id" element={<Detail shoes={shoes} />} /> // 여기서 :id가 URL 파라미터임

 

 

 

- useParams(): 유저가 URL 파라미터에 입력한 거 가져옴

function Detail(props) {

  let {id} = useParams(); // 입력

    return (
      <div className="container">
        <div className="row">
          <div className="col-md-6">
            <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
          </div>
          <div className="col-md-6">
            <h4 className="pt-5">{props.shoes[id].title}</h4> // 입력
            <p>{props.shoes[id].content}</p> // 입력
            <p>{props.shoes[id].price}원</p> // 입력
            <button className="btn btn-danger">주문하기</button> 
          </div>
        </div>
      </div> 
    )
  }

 

 

배열의 특정 값 찾기(find(), filter())

- find(): 배열에서 특정 값을 찾는 조건을 callback 함수를 통해 전달하여,조건에 맞는 값 중 첫번째 값을 리턴한다. 만약 배열에 조건을 만족하는 값이 없으면 undefined를 리턴한한다.

 

 

 

styled-components 쓰면 CSS 파일 없어도 되는데


컴포넌트가 많은 경우 스타일링을 하다보면 불편함이 생기는데

1. class 만들어놓은걸 까먹고 중복해서 또 만들거나

2. 갑자기 다른 이상한 컴포넌트에 원하지않는 스타일이 적용되거나

3. CSS 파일이 너무 길어져서 수정이 어렵거나

이런 경우가 있다.

 

그래서 스타일을 바로 입혀서 컴포넌트를 만들어버릴 수도 있는데 styled-components 라는 인기 라이브러리를 설치하여 이용하시면 된다.

let YellowBtn = styled.button`
  background: ${ props => props.bg };
  color: ${ props => props.bg == 'blue' ? 'white' : 'black'};
  padding: 10px;
`

 

<YellowBtn bg="blue">버튼</YellowBtn>
<YellowBtn bg="red">버튼</YellowBtn>

 

 

 

Lifecycle과 useEffect 1


- 컴포넌트의 Lifecycle 

컴포넌트는

1. 생성이 될 수도 있고 (전문용어로 mount)

2. 재렌더링이 될 수도 있고 (전문용어로 update)

3. 삭제가 될 수도 있다. (전문용어로 unmount)

 

컴포넌트의 lifecycle을 알고 있으면 간섭가능(= 중간중간 코드 실행가능)

ex) "Detail 컴포넌트 등장 전에 이것좀 해줘"

"Detail 컴포넌트 사라지기 전에 이것좀 해줘"

"Detail 컴포넌트 업데이트 되고나서 이것좀 해줘"

 

간섭은 갈고리를 달아서 코드를 넣어주면 됨 (hook)

 

 


useEffect 안에 적은 코드는 html 렌더링 이후에 동작한다.

 

function Detail(){

  (반복문 10억번 돌리는 코드)
  return (생략)
}

▲ 여기에  적으면 반복문 돌리고 나서 하단의 html 보여줌

 

 

 

function Detail(){

  useEffect(()=>{
    (반복문 10억번 돌리는 코드)
  });
  
  return (생략)
}

▲ useEffect 안에 적으면 html 보여주고 나서 반복문 돌림 

 

이런 식으로 코드의 실행 시점을 조절할 수 있기 때문에 조금이라도 html 렌더링이 빠른 사이트를 원하면 쓸데없는 것들은 useEffect 안에 넣으면된다. 

 

 

 

 

리액트에서 탭 UI 만들기


- Component 유의사항

 

1. 이름은 대문자로 시작하기

2. return() 안에 있는건 태그 하나로 묶어야 함( ex. div 태그로 묶기)

* div를 쓰기 싫으면  <></>로 묶으면 됨

 function Mdoal() {
    return (
      <>
      <div className='modal'>
        <h2>제목</h2>
        <p>날짜</p>
        <p>상세 내용</p>
      </div>
      <div></div>
      </>
    )
  }

 

 

 

 

- array 의 특징을 이용해서 if문 3개를 1개의 array로 축약함.

[<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][탭]