코딩 애플 React Part 2 - (1)

신승준·2022년 7월 5일
0

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


  • 부트스트랩의 특정 컴포넌트를 사용하려면 밑과 같이 import 해줘야 한다.
import logo from "./logo.svg";
import "./App.css";
import { Button, Navbar, Nav, Container,  } from "react-bootstrap";

function App() {
    return (
        <div className="App">
            <Button variant="primary">Primary</Button>
            <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;



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

  • JSX 상에서 태그를 이용해 바로 사진을 넣고 싶으면 다음과 같이 해야한다.
    • 경로로부터 쓰고자 하는 사진 import
    • 태그는 다음과 같이 작성. 문자열임을 주의해야 한다.
import bg from "./img/bg.png";

...

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

  • 하지만 위와 같이 할 경우, 사진이 많아지면 많아질수록 import를 겁나게 많이 해야 한다.
    • 따라서 public 폴더에 사진 파일을 저장하는 방법을 사용해도 된다.
      • 리액트는 src안의 파일들을 사이트 발행 전에 html, js, css 파일로 압축한다.(bundling)
        • 허나 public 폴더 안의 파일들은 압축되지 않는다.
        • public 폴더 안의 파일을 사용하고 싶다면 /logo192.png라고 쓰기만 하면 된다.
        • 가장 안전한 방법은 다음과 같다.
        • public 폴더는 단순히 / 만 붙여주면 된다.
<img src={process.env.PUBLIC_URL + '/logo192.png'} width="80%"></img>



코드가 길어지면 import export

* for문으로 생긴 HTML에는 각 HTML마다 key가 부여되어야 하는데, 자식 컴포넌트에서 props.key를 쓰는 것은 유효하지 않다.

  • 서버에서 데이터를 가져왔다고 가정.
  • 많은 데이터 등, 코드가 길어진다 싶으면 파일에다가 저장해두고, 이 파일의 데이터를 이용하는 방식으로 해서 코드를 간단하게 만들 수 있다.
    • 이 때 사용되는 문법이 import(수입), export(수출)이다.
    • 배열, 객체, 함수도 export 가능하다.
  • 1개의 데이터 import, export
    • data.js와 App.js에서 지은 이름이 달라도 된다.
      App.js
import name from './data.js';

...

    return (
        <div className="App">
			{name}
...

data.js

let a = 10;

export default a;       // 다른 파일에서 가져다 쓸 수 있는 변수가 된다.

  • 2개 이상의 데이터 import, export
    • 이 때는 이름이 달라지면 안된다. 그리고 App.js에서 중괄호가 필요해진다.

App.js


...

import {a, b} from './data.js'

function App() {
	let [shoes, setShoes] = useState();
	
    return (
        <div className="App">
			{b}

...

data.js

let a = 10;
let b = 20;

export {a, b};       // 다른 파일에서 가져다 쓸 수 있는 변수가 된다.

  • 과제
...

            <div className="container">
                <div className="row">
					{shoes.map(function (element, index) {
						return (
							<Content data={shoes[index]} key={index} index={index}></Content>	
						);
					})}
                </div>
            </div>
        </div>
    );
}

function Content(props) {
	return (
	<div className="col-md-4">
		{/* <img src={process.env.PUBLIC_URL + '/logo192.png'} width="80%"></img> */}
		{/* <img src="https://codingapple1.github.io/shop/shoes1.jpg" width="80%"></img> */}
		<img src={'https://codingapple1.github.io/shop/shoes' + (props.index + 1) + '.jpg'} width="80%"></img>
		<h4>{props.data.title}</h4>
		<p>{props.data.price}</p>
	</div>
		
	);

...



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

  • 여러가지 페이지를 만드는 방법
  • 원래라면 html 파일을 여러개 만들었었다.
    • 하지만 리액트에서는 index.html 파일 1개로 다 한다.

  • 리액트로 페이지 나누는 방법
    • 페이지가 바뀌어야 할 경우, 다른 html 파일로 가는 것이 아니라 index.html의 내용을 다 지우고 미리 만들어 놓은 컴포넌트로 index.html을 채운다.
    • 즉 누가 그 페이지에 접속할 경우 그 컴포넌트로 index.html을 채우는 것이다.

react-router-dom

  • 하지만 위와 같이 할 경우 코드가 길어진다.
  • 따라서 react-router-dom이라는 라이브러리를 사용한다.
    1. npm install react-router-dom@6 입력
    2. index.js에 다음과 같이 입력
...

import { BrowserRouter } from "react-router-dom";

...

root.render(
  <React.StrictMode>
    <BrowserRouter>
    <App />
    </BrowserRouter>
  </React.StrictMode>
  • 참고로 import에서 ./로 시작하는 것은 대부분 내가 만든 파일이고, ./ 없이 그냥 "", 이나 ''로 감싸져 있는 것은 라이브러리이다.
  1. App.js에서 다음 컴포넌트를 import
...

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

...

  • Route 컴포넌트는 페이지라고 생각하면 된다. 4개 페이지가 필요할 것 같으면 4개 써놓으면 된다.
    • 아래와 같이 작성한 것의 의미는
      • detail이라는 주소로 접속 시, element가 보여진다는 뜻이다.
  • 메인 페이지에다가 무언가 해주고 싶다면, 경로(path)에 "/"만 넣으면 된다.
<Route path="/" element={<div>메인페이지</div>}/>
<Route path="detail" element={<div>상세페이지</div>}/>
  • 다음과 같이 바꿔서 main과 상세페이지의 차이를 둘 수 있다.

...

<Routes>
	<Route
		path="/"
		element={
			<>
				<div className="main-bg"></div>
				<div className="container">
					<div className="row">
						{shoes.map(function (element, index) {
							return (
								<Card
									data={shoes[index]}
									key={index}
									index={index}
								></Card>
							);
						})}
					</div>
				</div>
			</>
		}
	/>
	<Route path="/detail" element={<div>상세페이지</div>} />
</Routes>

...

  • 사용자들은 URL로 페이지를 이동하지 않는다.
  • 따라서 페이지 이동버튼을 통해 움직이게 해줘야 한다.
    • 페이지 이동버튼은 Link 컴포넌트를 사용한다.
    • Link는 그냥 a 태그 같은 것들이 생성된다.
<Link to="/"></Link>
<Link to="/detail">상세페이지</Link>



리액트 라우터 2: navigate, nested routes, outlet

  • 폴더 구조

    • 거의 높은 확률로 우리가 만드는 파일의 종류는 js 파일이다.
    • 이를 잘 묶으려면 src 폴더 안에 폴더를 만들면 된다.
  • 이 때 주의할 점으로는 해당 파일을 사용하는 파일들의 import 경로를 잘 설정해주어야 한다.

import Detail from "./routes/Detail.js";

useNavigate

import { Routes, Route, Link, useNavigate, Outlet } from "react-router-dom";
  • 페이지 이동을 도와준다.
  • use가 들어가면 훅(Hook)이라고 부른다. 그냥 react에서 유용한 함수라고 보면 된다.

  • 다음과 같이 사용한다.
    • navigate 안에 -1을 넣으면 뒤로, 1을 넣으면 그 페이지에서 앞으로 가라는 뜻이다.
      • -2이면 뒤로 2번 간다.
<Nav.Link onClick={() => { navigate('/')}}>Home</Nav.Link>
<Nav.Link onClick={() => { navigate('/detail')}}>Detail</Nav.Link>
  • 404 페이지
    • 사용자가 허용된 페이지가 아닌, 오타 등 잘못된 주소로 접근할 때에
    • 지금 상태에서는 아무것도 뜨지 않는다.
    • 이를 잘못된 페이지에 접근했다고 명시적으로 알려주기 위해 404 페이지를 이용한다.
    • path에 *을 이용한다.
{/* /, /detail처럼 우리가 Route 해준 페이지를 제외한 모든 페이지들이 * */}
<Route path="*" element={<div>없는 페이지입니다.</div>}></Route>

  • Nested Routes
    • 예로, about이라는 페이지에서 member로, 또 location으로도 갈 수 있을 때
    • 다음과 같이 짤 수 있다.
<Route path="/about" element={<About></About>}/>
<Route path="/about/member" element={<About></About>}/>
<Route path="/about/location" element={<About></About>}/>
  • 위와 같이 하면 코드가 더러워질 수 있으니 다음과 같은 방법을 쓴다.
<Route path="/about" element={<About></About>}>
	<Route path="member" element={<About></About>}/>
	<Route path="location" element={<About></About>}/>
</Route>
  • 코드를 간단하게 만들면서도, 보여주는 element를 중복시킬 수 있다.

    • 다음과 같이 작성 시, About 컴포넌트 안에 'div 멤버임 div'도 포함해서 보여주겠다는 것이다.
    • 이를 위해서 Outlet을 사용해야 한다. About 컴포넌트 안에서 nested Route의 element가 어디에 위치해야 하는지를 나타내기 위함이다.
  • 즉 Route가 겹치면, 내용도 겹쳐지게 된다.

    • Outlet을 사용하지 않으면 상위 요소만 반영이 된다.
    • Outlet을 쓰더라도, element에 빈 태그를 삽입하면 하위 Route는 반영되지 않는다.

Nested Routes를 언제 쓰면 좋을까?

  • 여러 유사한 페이지가 필요할 때
    • 즉 페이지들마다 차이점이 별로 없을 때(박스 하나나 글자만 조금 바뀔 때)

Nested Routes의 장점

  • 페이지 이동이 쉬워진다.



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

여러 개의 페이지를 만들고 싶으면 URL 파라미터 사용

  • Route의 path에 /:id라고 작성하면, / 뒤에 아무거나 쳐도 해당 element를 보여주라는 뜻이다.
<Route path="/detail/:id" element={<Detail shoes={shoes}></Detail>}></Route>

useParams 훅

  • 사용자가 어떤 주소로 접근했을 때 그 주소의 인자들을 사용할 수 있게 해준다.
    • 밑과 같이 코딩이 되어 있을 경우, :id 부분의 파라미터를 Detail 함수에서 사용할 수 있게 된다.
    • 주의할 점으로는, Route의 id라는 변수와, Detail.js에서의 useParams에 사용되는 변수명은 같아야 한다.
<Route path="/detail/:id" element={<Detail shoes={shoes}></Detail>}></Route>

Detail.js

import {useParams} from "react-router-dom";

function Detail(props) {
    let {id} = useParams();
    console.log(id);
  
...
  • 다음과 같이 할 경우 id와 id2 등, 여러 가지의 인자를 사용할 수도 있다.
    • abcd는 인자가 아니다.
<Route path="/detail/:id/abcd/:id2" element={<Detail shoes={shoes}></Detail>}></Route>
  • 사용자가 URL에 이상한 문자를 칠 수 있으니 이는 if문으로 예외처리를 해줘야 할 수도 있다.
    • 404 페이지 뜨게 해야 되나?
profile
메타몽 닮음 :) email: alohajune22@gmail.com

0개의 댓글