[React] React Router와 useParams
하드코딩(반복 작업으로 불필요한 것 들을 다 코딩하는 방법)을 막는 방법 중 하나이다.
고객의 데이터가 몇십만개라고 치면, 그 몇십만개의 데이터에 해당하는 주소를 일일히 라우팅 하지 않는 방법이다.
마치 api에서 불러오는 자료들을 반복문이나 map함수를 이용해 반복하는 방식과 비슷하다.
예시코드
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import { BrowserRouter, Route, Switch, Link, NavLink } from "react-router-dom";
function Topics() {
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<NavLink to="/topics/1">HTML</NavLink>
</li>
<li>
<NavLink to="/topics/2">CSS</NavLink>
</li>
<li>
<NavLink to="/topics/3">JAVASCRIPT</NavLink>
</li>
</ul>
<Switch>
<Route path="/topics/1">HTML is ...</Route>
<Route path="/topics/2">CSS is ...</Route>
<Route path="/topics/3">JS is ...</Route>
</Switch>
</div>
);
}
function App() {
return (
<div>
<h1>React Router Dom example</h1>
<ul>
<li>
<NavLink to="/topics">Topics</NavLink>
</li>
</ul>
<Route path="/topics">
<Topics />
</Route>
</div>
);
}
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
간단히 라우터 내에 라우터를 코딩하는 방식이다.
이를 실행하면 아래와 같이 나타난다.
url을 자세히 보면 1, 2, 3으로 각각 숫자를 준 것을 알 수 있다.
이 숫자들을 수 많은 데이터를 관리한다고 생각하고 훅과 라우터의 기술로 자동으로 리스트와 라우터가 만들어지게 할 것이다.
우선 Topics 함수 위에 콘텐츠 객체들을 담은 배열인 contents를 만든다.
const contents = [
{id:1, title:'HTML', description:'HTML is ...'},
{id:2, title:'CSS', description:'CSS is ...'},
{id:3, title:'JS', description:'JS is ...'}
]
이 contents 배열은 예시처럼 하드코딩 하지 않을 것이고 보통은 이미 만들어진 데이터들을 가져오는 형식으로 사용 할 것이다. 또한, 이 객체의 숫자가 상당히 많다고 가정해야 한다.
Topics의 링크와 제목을 반복생성해보자.
function Topics() {
let topicTitleList = [];
for (let i = 0; i < contents.length; i++) {
topicTitleList.push(
<li>
<NavLink to={"/topics/" + contents[i].id}>
{contents[i].title}
</NavLink>
</li>
);
}
return (
<div>
<h2>Topics</h2>
<ul>
{topicTitleList}
</ul>
...
</div>
);
}
이렇게 하면 반복문으로 하드코딩이 필요가 없다.
이제는 path를 자동으로 생성 할 것이다.
우선 원래의 모양을 보자.
function Topics(){
...
return (
<div>
<h2>Topics</h2>
<ul>
{topicTitleList}
</ul>
<Switch>
<Route path="/topics/1">HTML is ...</Route>
<Route path="/topics/2">CSS is ...</Route>
<Route path="/topics/3">JS is ...</Route>
</Switch>
</div>
);
}
Switch 컴포넌트로 감싸져 있는 것들을 매개변수를 통해 라우팅해보자.
UseParams
파라미터는 즉 매개변수이다.
useparams 훅을 이용해 id와 라우트를 매치해주자.
import { BrowserRouter, Route, Switch, NavLink, useParams } from "react-router-dom";
function Topic(){
let params = useParams()
return (
<div>
<h3>Topic</h3>
Topic...
</div>
)
}
function Topics() {
let topicTitleList = [];
for (let i = 0; i < contents.length; i++) {
topicTitleList.push(
<li>
<NavLink to={"/topics/" + contents[i].id}>
{contents[i].title}
</NavLink>
</li>
);
}
return (
<div>
<h2>Topics</h2>
<ul>
{topicTitleList}
</ul>
<Route path="/topics/:topic_id">
<Topic></Topic>
</Route>
</div>
);
}
훅을 호출하는 것 처럼 useParams도 위와 같이 호출해준다.
useParams는 useRef 사용하듯 변수로 선언해준다.
그리고 Route path에 파라미터가 들어갈 곳은 /:topic_id라고 변수를 지정해준다.
params에 어떤 결과가 나오는지 콘솔로 확인해보자.
params가 클릭하는 콘텐츠의 id값을 topic_id로 받아오는 것을 볼 수 있다.
때문에, params.topic_id를 이용하면 해당 url에 특정 id의 콘텐츠를 받아올 수 있는 것이다!
function Topic(){ //파라미터를 Topic 함수에서 이용할 것을 암시
let params = useParams()
let topic_id = params.topic_id;
let selected_topic = {
title: 'Sorry',
desription: 'Not Found'
}
for (let i = 0; i < contents.length; i++){
if(contents[i].id === Number(topic_id)){
selected_topic = contents[i];
break;
}
} //topic_id가 존재하지 않으면 Not Found 나오게 하기. 그렇지 않으면 selected_topic을 contents[i]로.
return (
<div>
<h3>{selected_topic.title}</h3>
{selected_topic.description}
</div>
)
}
function Topics() {
let topicTitleList = [];
for (let i = 0; i < contents.length; i++) {
topicTitleList.push(
<li key={contents[i].id}>
<NavLink to={"/topics/" + contents[i].id}>
{contents[i].title}
</NavLink>
</li>
);
}
return (
<div>
<h2>Topics</h2>
<ul>
{topicTitleList}
</ul>
<Route path="/topics/:topic_id"> // /:변수 를 통해 해당 부분이 파라미터일 것을 암시
<Topic></Topic>
</Route>
</div>
);
}
최종적으로 위와 같이 코딩을 하면 간편하게 리액트 훅과 라우터를 이용해서 라우팅 할 수 있게 된다.
참고: