Basic_Studies/React & Next.js

[React] React Router와 useParams

adore_voy 2021. 1. 6. 21:29

하드코딩(반복 작업으로 불필요한 것 들을 다 코딩하는 방법)을 막는 방법 중 하나이다.

고객의 데이터가 몇십만개라고 치면, 그 몇십만개의 데이터에 해당하는 주소를 일일히 라우팅 하지 않는 방법이다.

마치 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>
    );
}

최종적으로 위와 같이 코딩을 하면 간편하게 리액트 훅과 라우터를 이용해서 라우팅 할 수 있게 된다.


참고:

생활코딩 React Router

반응형