라우팅
라우팅이랑 서버에서 클라이언트에 내가 불러오고자 하는 URL을 불러오는 것이다.
Static Routing(정적 라우터)
next/router 사용하기
import { useRouter } from 'next/router'
export default function StaticRoutingPage() {
const router = useRouter()
function onClickMove() {
router.push('/05-02-static-routed')
}
return (
<button onClick={onClickMove}>페이지 이동하기</button>
)
}
const router = useRouter()
router.push('이동할 페이지')
reloae(), replace(),
- pathname: 현재 나의 주소를 알려준다
import { useRouter } from 'next/router'
export default function StaticRoutingNumberPage() {
const router = useRouter()
function onClickMove1() {
router.push('/05-04-static-routed-number/1')
}
function onClickMove2() {
router.push('/05-04-static-routed-number/2')
}
function onClickMove3() {
router.push('/05-04-static-routed-number/3')
}
return (
<>
<button onClick={onClickMove1}>1번 게시글</button>
<button onClick={onClickMove2}>2번 게시글</button>
<button onClick={onClickMove3}>3번 게시글</button>
</>
)
}
게시글의 수가 많아지면 폴더의 수가 많아지므로 비효율적인 방법이다.
Dynamic Routing(동적 라우터)
SPA(Singe Page Application)의 라우팅 과정
기존에는 서버로부터 해당 URL에 대한 데이터를 받아왔으나 이제는 하나의 큰 앱을 받아오는 것이며, 클라이언트(브라우저)에 해당 URL에 따라서 어떤 것을 보여줄지 결정한다.
->한 번에 앱을 받아오고 내부에서 작동하는 형식
- 브라우저에서 최초에 '/'루트 경로로 요청
- reace web app을 내려주고
- 내려받은 reac app 에서 루트 경로에 맞는 컴포넌트를 보여준다.
- react app에 다른 페이지로 이동하는 동작을 수행하면
- 새로운 경로에 맞는 컴포넌트를 보여준다.
next/router
[폴더이름]
으로 변수 형태의 폴더를 생성해준다.
http://localhost:3000/boards/`[폴더이름]`
import { useRouter } from 'next/router'
export default function DynamicRoutingNumberPage() {
const router = useRouter()
router.query = {
}
function onClickMove1() {
router.push('/05-06-dynamic-routed-number/1')
}
function onClickMove2() {
router.push('/05-06-dynamic-routed-number/2')
}
function onClickMove3() {
router.push('/05-06-dynamic-routed-number/3')
}
return (
<>
<button onClick={onClickMove1}>1번 게시글</button>
<button onClick={onClickMove2}>2번 게시글</button>
<button onClick={onClickMove3}>3번 게시글</button>
</>
)
}
import { useRouter } from "next/router"
export default function DynamicRoutedNumberPage() {
const router = useRouter()
return (
<div>{router.query.number}번 게시글 이동완료</div>
)
}
react-router
react는 컴포넌트를 작성하고 렌더하며, 라우팅을 시행하기 위해서는 react-router 라이브러리를 사용해주어야한다. 가장 대표적으로 라우팅을 해주는 패키지이며 cra에 기본 내장된 패키지가 아니기 때문에 react-router를 사용하려면 설치를 진행해주어야 한다.
npm i react-router-dom
특정 경로에서 보여줄 컴포넌트를 준비한다.
import { BrowserRouter, Route } from "react-router-dom"
import Home from "./pages/Home"
export default function App() {
return(
<BrowserRouter>
<Route path="/" componenet={Home} />
</BrowserRouter>
)
}
app.js에서 return 하단에 Route 컴포넌트에 역에 경로(path)와 컴포넌트(component)를 설정한다.
이것을 BrowserFouter로 감싸주고 브라우저에서 요청한 경로에 Route의 path가 들어잇으면 해당 컴포넌트를 보여준다.
여기서 만약
<BrowserRouter>
<Route path="/" componenet={Home} />
<Route path="/profile" componenet={Profile} />
</BrowserRouter>
두 가지 컴포넌트가 있을 때 profile 컴포넌트를 불러오기 위하여 /profile을 사용하면 Home과 Profile 컴포넌트 두 가지가 모두 보여지는데, 이는 Home의 path가 '/'이기 때문에 profile의 path인 '/profile'에 포함되어 있기 때문이다.
이를 정확하게 수정해주기 위해서는 exact로 해당 path와 정확히 일치하는 경우에만 해당 컴포넌트를 불러오도록 설정해주면 된다.
<BrowserRouter>
<Route path="/" exact componenet={Home} />
<Route path="/profile" exact componenet={Profile} />
</BrowserRouter>
<BrowserRouter>
<Route path="/" exact componenet={Home} />
<Route path="/profile" exact componenet={Profile} />
<Route path="/profile/:id" componenet={Profile} />
</BrowserRouter>
export default function Profile(props) {
const id = props.match.params.id
return
<div>
<h2>프로필페이지입니다.</h2>
{ id && <p>id는 {id} 입니다.</p>}
</div>
}
쿼리 스트링
<BrowserRouter>
<Route path="/" exact componenet={Home} />
<Route path="/profile" exact componenet={Profile} />
<Route path="/profile/:id" componenet={Profile} />
<Route path="/about" exact componenet={About} />
</BrowserRouter>
export default function About(props) {
const searchParams = props.location.search
const obj = new URLSearchParams(searchParams)
const name = obj.get("name")
return
<div>
<h2>About 페이지입니다.</h2>
{name && <p>는 이름은 {name} 입니다.</p>}
</div>
}
-> URLSearchParams는 바로 key로 꺼내쓰지못하며 브라우저에 따라 지원이 되지 않을 수 있다. 그러므로 query-string을 받아서 사용해주면 좋다.
query-string 사용하기
npm i query-string
import queryString from 'query-string'
export default function About(props) {
const searchParams = props.location.search
const query = queryString.parse(searchParms)
return <div>About 페이지입니다.</div>
{query.name && <p>는 이름은 {query.name} 입니다.</p>}
}
조건부 렌더링
&& 연산자
import { useQuery,gql } from "@apollo/client"
import { useRouter } from "next/router"
const FETCH_PRODUCT = gql`
query fetchProduct($productId: ID) {
fetchProduct(productId: $productId) {
seller
name
detail
price
}
}
`
export default function DynamicProductRead() {
const router = useRouter()
const { data } = useQuery(FETCH_PRODUCT, {
variables: { productId: router.query.myId }
})
return (
<>
<div>판매자 {data && data.fetchProduct.seller}</div>
<div>상품명 {data && data.fetchProduct.name}</div>
<div>상품상세 {data && data.fetchProduct.detail}</div>
<div>상품가격 {data && data.fetchProduct.price}</div>
</>
)
}
삼항연산자
data ? data.fetchProduct.seller : "loading"
// ? 있으면
// : 없으면
optional chaining
// 있으면 보여주고 없으면 보여주지 마세용
data?.fetchProduct.seller
try-catch 구문
async function zzz() {
try {
// 일단 시도해보고
const result = await createProduct({
variables: {
seller: mySeller,
createProductInput: {
name: myName,
detail: myDetail,
price: Number(myPrice)
}
}
})
console.log(result)
router.push(`05-08-dynamic-product-read/${result.data.createProduct._id}`)
} catch(error) {
// 에러나면 이렇게 실행해주세요
alert(error.message)
}
}
기타
주석
+) graphql 주석 시 # 사용, emotion 주석 시 /* */ 사용(HTML)과 같음. graphql은 평소처럼 ctrl+/ 사용해도 주석 오류가 발생하니 주의하도록합시다!
템플릿 리터럴
router.push(`05-08-dynamic-product-read/${result.data.createProduct._id}`)