Next.js Movie App 만들기- style, global style, patterns, Fetching Data

Jiwontwopunch·2022년 7월 12일
0

독학

목록 보기
96/102
post-thumbnail

$ npx create-next-app@latest

$ project named? nextjs-intro

$ code nextjs-intro

README.md

# Nextjs Introduction

$ npm run dev

http://localhost:3000 브라우저 확인

pages에 있는 파일 전부 삭제

pages/index.js

react같은 library를 사용할 때는 원할 때 언제든 어떤 방법으로든 부르면 된다. 하지만 next.js같은 framework에서는 특정한 규칙을 따라야한다. 파일의 이름이 중요하다. jsx도 사용할 수 있다.

// 앱의 홈은 기본적으로 index.js에서 나온다. 

export default function Home() {
  return "Hi"
}

pages/about.js

export default function Potato(){
  return "about us"
}

http://localhost:3000/about 브라우저 확인

pre-rendering & hydration

next.js의 가장 좋은 기능 중 하나는 앱에 있는 페이지들이 미리 렌더링 된다는 점이다. hydration은 react.js를 프론트엔드 안에서 실행하는 것을 말한다. next.js는 react.js를 백엔드에서 동작시켜서 페이지를 미리 만드는데 이게 component들을 render시킨다. 렌더링이 끝났을 때 그건 HTML이 되고 next.js는 그 HTML을 페이지의 소스코드에 넣어준다. 유저는 자바스크립트와 react.js가 로딩되지 않았더라도 콘텐츠를 볼 수 있게된다. 그리고 react.js가 로딩 되었을 때 기본적으로 이미 존재하는 것들과 연결이 되어서 일반적인 react.js 앱이 된다. SEO에 매우 좋다.

components/NavBar.js

// next.js 어플리케이션의 클라이언트 사이드 네비게이션을 제공해준다.
import Link from 'next/link';
import {useRouter} from 'next/router';

export default function NavBar(){
  const router = useRouter();
  console.log(router); // location에 관한 정보들을 얻는다.
  return (
  <nav>
    <Link href="/">
      <a className='hello' style={{color:router.pathname==="/" ? "red" : "blue"}}>Home</a>
    </Link>
    <Link href="/about">
    <a className='about' style={{color:router.pathname==="/about"? "red" : "blue"}}>About</a>
    </Link>
  </nav>
  );
}
// index.js
import NavBar from "../components/NavBar";

export default function Home() {
  return(
    <div>
      <NavBar />
      <h1>Home</h1>
    </div>
  )
}

// about.js
import NavBar from "../components/NavBar";

export default function Potato(){
  return <div>
    <NavBar />
    <h1>About</h1>
  </div>
}

style 다루기

  1. inline style
  2. modules 사용 NavBar.module.css
    import할 때 자바스크립트 오브젝트에서의 프로퍼티 형식으로 적어야 한다!!!
// NavBar.module.css
.active {
  color: tomato;
}

.link {
  text-decoration: none;
}

// NavBar.js
// next.js 어플리케이션의 클라이언트 사이드 네비게이션을 제공해준다.
import Link from 'next/link';
import {useRouter} from 'next/router';
import styles from './NavBar.module.css';

export default function NavBar(){
  const router = useRouter();
  console.log(router); // location에 관한 정보들을 얻는다.
  return (
  <nav>
    <Link href="/">
      <a className={`${styles.link} ${router.pathname==="/"? styles.active : ""}`}>Home</a>
    </Link>
    <Link href="/about">
    <a className={[
      styles.link, 
      router.pathname==="/about"? styles.active: "",]
      .join(" ")}>About</a>
    </Link>
  </nav>
  );
}
  1. styled JSX
// 형태
    <style jsx>{`
      nav {
        background-color: tomato;
      }
      a {
        text-decoration: none;
      }
    `}</style>


// NavBar.js
import Link from 'next/link';
import {useRouter} from 'next/router';

export default function NavBar(){
  const router = useRouter();
  console.log(router); // location에 관한 정보들을 얻는다.
  return (
  <nav>
    <Link href="/">
      <a className={router.pathname==="/"? "active": ""}>Home</a>
    </Link>
    <Link href="/about">
    <a className={router.pathname==="/about"? "active": ""}>About</a>
    </Link>
    <style jsx>{`
    nav {
      background-color: tomato;
    }
    a {
      text-decoration: none;
    }
    .active {
      color: yellow;
    }
    `}</style>
  </nav>
  );
}
  1. Global style
    App Component는 일종의 어떤 컴포넌트의 청사진으로 볼 수 있다.
    커스터마이즈하려면 어떤 파일을 하나 만들어야 하는데 이름은 무조건 _app.js로 만들어야 한다.
// components/_app.js
import NavBar from "../components/NavBar";
// _app.js에서는 golbal styles를 import할 수 있다.
import "../styles/globals.css";

export default function App({Component, pageProps}){
  return (
    <div>
  <NavBar />
  <Component {...pageProps} />
  <span>hello</span>
  <style jsx global>{`
  a {
    color: white;
  }
  `}</style>
  </div>
  )
}

Patterns

// components/Layout.js
import NavBar from "./NavBar"

export default function Layout({children}){
  return (
  <>
  <NavBar />
  <div>{children}</div>
  </>
  )
}

// components/Seo.js
import Head from "next/head";

export default function Seo({title}){
  return (
  <Head>
    <title>{title} | Next Movies</title>
  </Head>
  );
}

// index.js
import Head from "next/head";
import Seo from "../components/Seo";

export default function Home() {
  return(
    <div>
      <Seo title="Home" />
      <h1 className="active">Home</h1>
    </div>
  )
}

// about.js
import Head from "next/head";
import Seo from "../components/Seo";

export default function Potato(){
  return (
  <div>
    <Seo title="About" />
    <h1 className="active">About</h1>
  </div>
  )
}

Fetching Data

https://www.themoviedb.org/ 에서 데이터를 가져와 사용할 것
1. API key
2. API - API개요(API Overview) - developers.themoviedb.org. 클릭 -
Movies, GET /movie/popular - Movies, Try it out

// index.js
import { useEffect, useState } from "react";
import Seo from "../components/Seo";

const API_KEY="ca91d4fe545a80a5a8f72d6881928f5c";

export default function Home() {
  const [movies, setMovies] = useState();
  useEffect(()=>{
    (async()=>{
      const {results}=await (
        await fetch(
        `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
        )
        ).json();
        // console.log(data);
        setMovies(results);
  })();
},[]);
  return(
    <div className="container">
      <Seo title="Home" />
      {!movies && <h4>Loading...</h4>}
      {movies?.map((movie)=>(
        <div className="movie" key={movie.id}>
          <img src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`} />
          <h4>{movie.original_title}</h4>
        </div>
      ))}
      <style jsx>{`
      .container {
        display: grid;
        grid-template-columns: 1fr 1fr;
        padding: 20px;
        gap: 20px;
      }
      .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>
  );
}

// NavBar.js
// next.js 어플리케이션의 클라이언트 사이드 네비게이션을 제공해준다.
import Link from 'next/link';
import {useRouter} from 'next/router';

export default function NavBar(){
  const router = useRouter();
  console.log(router); // location에 관한 정보들을 얻는다.
  return (
  <nav>
    <img src="/vercel.svg"/>
    <div>
    <Link href="/">
      <a className={router.pathname==="/"? "active": ""}>Home</a>
    </Link>
    <Link href="/about">
    <a className={router.pathname==="/about"? "active": ""}>About</a>
    </Link>
    </div>
    <style jsx>{`
    nav {
      display: flex;
      gap: 10px;
      flex-direction: column;
      align-items: center;
      padding-top: 20px;
      padding-bottom: 10px;
      box-shadow: rgba(50,50,93,0.25) 0px 50px 100px -20px,
                         rgba(0,0,0,0.3) 0px 30px 60px -30px;
    }
    img {
      max-width: 100px;
      margin-bottom: 5px;
    }
    nav a {
      font-weight: 600;
      font-size: 18px;
    }
    .active {
      color: tomato;
    }
    nav div {
      display: flex;
      gap: 10px;
    }
    `}</style>
  </nav>
  );
}

0개의 댓글