카테고리 없음

useNavigate, useLocation, useParams Hook

heejunn 2022. 5. 7. 19:21

  1. 카드를 클릭하면, onClick 이벤트시 발생하는 navigate 함수를 통해 /product/1 로 이동한다.
  2. URL 이 /product/1 로 변하면, Router 컴포넌트에 정의되어 있는 path='/product/:id' 에 따라, ProductDetail 컴포넌트가 마운트 된다.
  3. ProductDetail 컴포넌트에서는 백엔드에 id 가 1 인 아이템에 대한 정보를 요청
  4. 응답으로 받은 정보를 setData 함수를 통해 data 라는 state에 저장하고, 이를 통해 상세 페이지 UI 가 그려진다.

2번에서, ProductDetail 컴포넌트의 useEffect 훅을 통해 백엔드에 id 가 1 에 해당하는 정보를 요청했다. 그런데, 1 은 URL 에 담겨 있다(/product/1). ProductDetail 컴포넌트에서는 이것을 어떻게 가져올 수 있을까 ?

 

 

React Router 에서는 useNavigate, useLocation, useParams 라는 라우팅 관련한 훅을 제공한다. 이 중 useParams 훅을 사용하면 url 에 담겨있는 id 값을 가져올 수 있다.

useNavigate Hook

useNavigate

function Product(props) {
  const navigate = useNavigate();

  const goToDetail = () => {
    navigate(`/product/${props.id}`);
  }
  
  return (
    <div className="productContainer" onClick={goToDetail}>
	...
    </div>
  )
}

useNavigate 훅을 실행하면 페이지를 이동시키는(url을 변경시키는) 함수를 반환한다. 위 예제 코드에서 해당 함수를 navigate 라는 변수에 할당하였습니다. 따라서, navigate()와 같은 방식으로 함수를 호출할 수 있다.

navigate() 함수의 인자에 이동하고자 하는 url(ex. /products)을 전달하면, 해당 url로 화면을 이동합니다.

navigate('/product/1'); // '/product/1' 로 이동

인자에 정수값을 넣어주면 브라우저 방문 기록에 남아있는 경로들을 앞 뒤로 탐색할 수도 있습니다.

navigate(-1); // 뒤로 가기
navigate(-2); // 뒤로 2페이지 가기
navigate(1);  // 앞으로 가기

useLocation Hook

useLocation

function ProductDetail(props) {
  const location = useLocation();
  console.log(location);
  
  return (
    ...
  )
}

useLocation 훅을 실행하면 경로 정보를 담고 있는 객체 를 반환합니다. 위 코드에서 해당 객체를 location 이라는 변수에 할당해 주었습니다. location 변수를 콘솔로 출력해 보면 다음과 같은 로그가 출력 됩니다.

{
  pathname: '/product/1', 
  search: '', 
  hash: '', 
  state: null, 
  key: 'default'
}

여러가지 정보가 있는데, 여기서 주목할 부분은 pathname  search 프로퍼티 입니다.

  • pathname: 현재 경로 값
  • search: 현재 경로의 query parameter 값

useParams Hook

useParams

// 현재경로: /product/1

function ProductDetail(props) {
  const params = useParams();
  
  console.log(params);

  return (
    ...
  )
}

useParams 훅을 실행하면 path parameter 정보를 담고 있는 객체 를 반환합니다. 위 코드에서 해당 객체를 params 라는 변수에 할당해 주었습니다. params 변수를 콘솔로 출력해 보면 다음과 같은 로그가 출력 됩니다.

{
  id: 1
}

여기서 id 라는 프로퍼티 키 네임은 Router 에서 :id 로 표기해준 값 입니다.

<BrowserRouter>
  <Routes>
    <Route path='/product/:id' element={<ProductDetail />} />
  </Routes>
</BrowserRouter>

만약 :productId 라고 표기 했다면 다음과 같은 객체가 출력됩니다.

{
  productId: 1
}

정리하자면,

  • useNavigate 훅은 url 를 변경하는 함수 를 반환하고
  • useLocation 훅은 현재 경로 정보를 담고 있는 객체 를 반환하고
  • useParams 훅은 Router 에 등록해준 path parameter 정보를 담고 있는 객체 를 반환합니다.

4. useParams().id

다시 돌아와서, 어떻게 URL 에 담겨있는 id 값을 가져올 수 있을까요?

useParams 훅을 이용하여 가져올 수 있습니다. Path Parameter 로 명시해둔 값은 useParams 훅이 리턴하는 객체에 담기기 때문입니다.

// ProductDetail.js
// current url -> localhost:3000/product/1

function ProductDetail() {
  const params = useParams();

  console.log(params.id) // 1

  return (
    ...
  );	
}

따라서 useEffect 훅에서 해당 id 값을 통해 서버에 요청을 보내는 것을 통해 원하는 정보를 받아올 수 있습니다.

useEffect(() => {
  fetch(`${API}/${params.id}`)
    .then(res => res.json())
    .then(res => setData(res));
},[]);


위에서 봤던 예제를 다시한번 보자.

  • 리스트 페이지의 개별 상품을 클릭 → navigate("/product/1") 로 상세 페이지로 이동합니다.
  • 상세 페이지로 이동하면 url은 "http://localhost:3000/product/1" 과 같이 변경되어 있습니다.
  • 페이지에 필요한 데이터를 useEffect 에서 fetching 합니다.
    • 필요한 id는 URL에 존재하므로 useParams().id 에서 가져올 수 있습니다.
    • 해당 id를 가지고 백엔드에서 만들어준 API를 호출합니다.
    • function ProductDetail() { const params = useParams(); useEffect(() => { const productId = params.id; fetch(`http://123.456.789:8000/products/${productId}`) // 1 .then(res => res.json()) .then(res => setData(res)); },[]); return ( ... ) }
  • 서버에서 가져온 데이터(res)를 컴포넌트의 data state 에 저장해 줍니다.
  • state 에 담긴 데이터로 컴포넌트 UI 를 render 해줍니다.