[Next] useRouter(.push(url, as))와 Link(href, as)를 이용해 navigate하는 방법 & URL query 지정 및 내용 가져오기

쿼카쿼카·2022년 10월 17일
0

React / Next

목록 보기
10/34
// next.config.js

// .env에서 API_KEY 가져오기
const API_KEY = process.env.API_KEY;

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
}

module.exports = {
  nextConfig,
  async redirects() {
    return [
      {
        source: '/contact',
        destination: '/form',
        permanent: false,
      },
      {
        source: '/old-blog/:path*',
        destination: '/new-blog/:path*',
        permanent: false,
      }
    ]
  },
  async rewrites() {
    return [
      {
        source: '/api/movies',
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
      },
      // id 가져오는 rewrite
      {
        // :id로 변수 설정
        source: '/api/movies/:id',
        // 위 destination 링크에서 popular만 :id로 변경
        destination: `https://api.themoviedb.org/3/movie/:id?api_key=${API_KEY}`
      }
    ]
  }
}
// index.js

import Link from "next/link";
import { useRouter } from "next/router";
import Seo from "./Seo"

export default function Home({results}) {
  // router를 이용하여 페이지 이동 함수 만들기
  const router = useRouter();
  // 매개변수에 title 추가
  function onClick(id, title) {
    // push의 첫 매개변수: 이동할 url
    router.push({
      // pathname: 이동할 url
      pathname: `/movies/${id}`,
      // query: url에 쿼리로 나타낼 내용(? 뒷부분에 &로 구분하여 나타냄)
      // 숨겨지더라도 개발자도구 query에 나타남. 이를 이용해 제목도 전달 받을 수 있음
      query: {
        title,
      }
      // push의 두 번째 매개변수: as(겉으로 보여질 url)
    }, `/movies/${id}`);
  }
  return (
    <div className="container">
      <Seo title='Home' />
      {results?.map(movie => (
        // onClick에 매개변수를 넣어줘야하므로 콜백 함수 형태로 만듬
        <div onClick={() => onClick(movie.id, movie.original_title)} className="movie" key={movie.id}>
          <img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
          <h4>
            {/* Link에 href 설정 후 a태그로 제목 감싸기 */}
            {/* Link로 링크 이동을 원한다면 router.push와 같은 형태로 만들어줘야 함(href와 as 프로퍼티 이용) */}
            <Link href={{
              pathname: `/movies/${movie.id}`,
              query: {
                title: movie.original_title,
              }
            }} as={`/movies/${movie.id}`}>
              <a>
                {movie.original_title}
              </a>
            </Link>
          </h4>
        </div>
      ))}
      <style jsx> {`
        .container {
          display: grid;
          grid-template-columns: 1fr 1fr;
          padding: 20px;
          gap: 20px;
        }
        .movie {
          cursor: pointer;
        }
        .movie img {
          max-width: 100%;
          border-radius: 12px;
          transition: transform 0.2s ease-in-out;
          box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
        }
        .movie:hover img {
          transform: scale(1.05) translateY(-10px);
        }
        .movie h4 {
          font-size: 18px;
          text-align: center;
        }
      `}
      </style>
    </div>
  )
}

export async function getServerSideProps() {
  const {results} = await (await fetch('http://localhost:3000/api/movies')).json();

  return {
    props: {
      results,
    }
  }
}
// [id].js

import { useRouter } from "next/router";

export default function Detail() {
  const router = useRouter();
  console.log(router);
  return (
    <div>
      {/* router.query.title은 Home에서 클릭으로 넘어왔을 때만 존재 */}
      {/* 링크로 직접 들어오면 Loading만 뜸 */}
      <h4>{router.query.title || "Loading..."}</h4>
    </div>
  );
}

next.confing.js에서 rewrite 설정

useRouter.push(url, as)

  • router 변수에 useRouter 할당

  • router.push는 navigate해주는 함수

    • 첫 매개변수: 이동할 url 주소
      • /movies/${id} 처럼 그냥 주소만 적어줘도 됨
      • 객체 형태로 만들 수 있음
        • pahtname: 이동할 url
        • query: ? 뒷부분에 추가하고 싶은 내용(여러 개가 있으면 &로 구분됨)
    • 두 번째 매개변수: as(겉으로 보여질 URL)
      • url에 숨기고 싶은 정보를 가려주는 역할
      • /movies/${id} 처럼 생으로 적어줌
  • as가 없을 때(원래 query에 id, title이 있었음)

  • as가 있을 때

    • url에는 안 보이지만 [id].js에서 router를 console에 찍어보면 쿼리들이 잘 있음

    • 즉!!! 쿼리를 통해 정보를 받을 수 있다는 말씀!!

    • 그래서 title까지 onClick으로 받아 [id].js에 띄워준다~~

  • 하지만 onClick으로 만든 만큼 클릭을 통해 들어갈 때만 router.push가 작동하고, 직접 url을 쳐서 들어가면 [id].js에 써있는 것처럼 'Loading...'이 뜬다.

Link(href as)

  • Link 내에 a태그로 감싸 useRouter와 같이 navigate 기능
    • 예전에는 a태그가 어찌 div를 감싸냐며 꼭 글씨만 감싸라고 했는데 요새는 된다고 합니다^_^
    • 그냥 className='movie'인 div 상위에 <Link key={movie.id}><a>로 묶어주기(key 옮기는 거 안 하면 에러)
  • Link의 프로퍼티
    • href
      • 이동할 경로 지정(useRouter.push와 같은 형태 가능)
      • {{pathname, query}} 가능
    • as
      • 위와 동일

까먹었던 것

profile
쿼카에요

0개의 댓글