library : 내가 원하는 것을 언제든지 가져다가 씀
framework : 정해진 틀이 있고 규칙만 지켜서 쓰면 편하게 쓰기 가능
--> 만약 클라이언트 쪽에서 JS를 비활성화하면 동작하지 않음
--> 만약 클라이언트 쪽에서 JS를 비활성화해도 동작함
--> JS를 비활성화하면 버튼이나 이런건 동작하지 않음
--> 단점으로 API등을 가져올때 느릴 수 있음
--> 연결이 느려도 기다리면 확인 가능
export default function NavBar() {
return (
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
)
}
위와 같이 코드를 작성해도 동작은 한다
문제는 NavBar가 동작할때마다 전체 페이지를 새로고침을 한다
이는 속도를 느리게 만들 수 있다
그래서 우리는 <a>
말고 Link
를 사용한다
이거는 React의 router link랑 동일한거니깐 잘 기억해야한다
그러면 위 코드는 아래와 같이 수정된다 (속도도 훨씨이이인 빠른다)
그리고 버전에 따라 <Link><a></a></Link>
를 쓰는 것도 있는거 같다 (노마드 코드는 그렇게 쓰고있음 - 근데 내꺼는 저렇게 쓰면 <a>
를 지우라는 에러가 뜬다)
import Link from "next/link"
export default function NavBar() {
return (
<nav>
<Link href="/">
Home
</Link>
<Link href="/about">
About
</Link>
</nav>
)
}
그런데 개발자모드에서 검사로 보면 아래와 같이 <a>
로 표기되는 것을 알 수 있다.
근데 Link 안에 style, className 같은건 적용할 수 없다고 했는데..?
된다 지금은 됩니다.
<a> tag
를 넣으면 에러를 띄운다
import Link from "next/link"
export default function NavBar() {
return (
<nav>
{/* <Link legacyBehavior href="/">
<a style={{color: 'red'}}>Home</a>
</Link> */}
<Link style={{color: 'red'}} href="/">
Home
</Link>
<Link href="/about">
About
</Link>
</nav>
)
}
NextJS는 React랑은 다르게 router를 따로 install 하지 않아도 된다
그냥 불러와서 쓰면된다
아래처럼
import Link from "next/link"
import { useRouter } from "next/router"
export default function NavBar() {
const router = useRouter();
return (
<nav>
{/* <Link legacyBehavior href="/">
<a style={{color: 'red'}}>Home</a>
</Link> */}
<Link style={{color: router.pathname === "/"? "red":"blue"}} href="/">
Home
</Link>
<Link style={{color: router.pathname === "/about"? "red":"blue"}} href="/about">
About
</Link>
</nav>
)
}
아래 코드처럼 쓰면 동작하지 않는다
import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"
export default function NavBar() {
const router = useRouter();
return (
<nav className="nav">
{/* <Link legacyBehavior href="/">
<a style={{color: 'red'}}>Home</a>
</Link> */}
<Link href="/">
Home
</Link>
<Link href="/about">
About
</Link>
</nav>
)
}
아래와 같이 적어야 동작한다
import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"
export default function NavBar() {
const router = useRouter();
return (
<nav className={styles.nav}>
{/* <Link legacyBehavior href="/">
<a style={{color: 'red'}}>Home</a>
</Link> */}
<Link href="/">
Home
</Link>
<Link href="/about">
About
</Link>
</nav>
)
}
그건 그렇고 동작을 완료하니 아래처럼 이상한 말로 써진 class가 생성됐다
난 분명 코드에서 nav 를 썼는데..
이는 css module의 역할이라서 그런다. 이런식으로 만들게 되면 클래스 네임이 중복되는 현상을 막을 수 있다
그리고 class를 중복 적용하려면 아래와 같이 두가지 방법을 사용할 수 있다
import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"
export default function NavBar() {
const router = useRouter();
return (
<nav >
{/* <Link legacyBehavior href="/">
<a style={{color: 'red'}}>Home</a>
</Link> */}
<Link className={`${styles.link} ${router.pathname === "/" ? styles.active : ""}`} href="/">
Home
</Link>
<Link className={[
styles.link,
router.pathname === "/about" ? styles.active : "",
].join(" ")} href="/about">
About
</Link>
</nav>
)
}
그런데 노마드코더는 둘다 좋아하지 않는다고 했음
왜냐면
1. 파일을 두개 써야함 (js, module.css)
2. 조건부 연산자를 쓰는게 복잡함
이 두가지를 해결하는걸 이제 다음장에서 해보자
아래처럼 직접 쓰면된다 style jsx 그리고 `` 백틱을 사용해서
그리고 이는 독립적으로 움직여서 다른 페이지에 영향을 주지 못한다
NavBar.js
import Link from "next/link"
import { useRouter } from "next/router"
export default function NavBar() {
const router = useRouter();
return (
<nav>
<Link legacyBehavior href="/">
<a>Home</a>
</Link>
<Link legacyBehavior href="/about">
<a>About</a>
</Link>
<style jsx>{`
nav {
background-color: tomato;
}
a{
text-decoration: none;
}
`}</style>
</nav>
)
}
index.js
import NavBar from "@/components/NavBar";
export default function Home() {
return (
<div>
<NavBar />
<h1>Hello</h1>
<style jsx>{`
a{
color: white;
}
`}</style>
</div>
);
}
위 처럼 두개의 <a> tag
에 적용될수 있는게 코드상으로 두개의 style이 있지만 아래 그림을 보면 실제는 NavBar.js만 적용된 것을 알 수 있다
위에서 말했던 css.module 사용시 발생한다고 느낀 2가지 단점이 다 없어진 것을 확인할 수 있다.
그러면 전역으로 Css를 어떻게 설정할 수 있을까??
그건 이제부터 해봅시다
import NavBar from "@/components/NavBar";
export default function Home() {
return (
<div>
<NavBar />
<h1>Hello</h1>
<style jsx global>{`
a{
color: white;
}
`}</style>
</div>
);
}
위에 처럼 style jsx global을 하는 것도 하나의 방법이다
하지만 위처럼 하게 될 경우 상속관계가 아닌 페이지 이동의 경우 적용이 되지 않는다
react는 page별로 생각하지 않아도 되지만 NextJS는 해줘야한다
이를 해결하기위해서 NextJS에는 pages 폴더 안에 _app.js
를 사용할 수 있게 해놨다 (파일명은 무조건 _app.js를 써야한다 그래야 모든 파일중에 가장 먼저 rendering 이됨)
_app.js
import NavBar from "@/components/NavBar";
export default function App({ Component, pageProps }) {
return (
<>
<NavBar />
<Component {...pageProps} />
<style jsx global>{`
a{
color: white;
}
`}</style>
<span>hello</span>
</>
)
}
위 코드를 한줄씩 뜯어보면
import는 NavBar를 불러온거다 (@를 써서 절대경로로 불렀음)
Component 는 pages에 있는 index.js, about.js 등 각각의 page를 얘기한다
pageProps 는 page 안에 있는 properties 를 얘기한다
즉 <Component {...pageProps} />
는 각각의 page를 가져와서 rendering 하는 부분이다.
위에처럼 작성하면 NavBar, style jsx, span은 전부 global로 동작하게 된다
global.css는 각각의 page에서 불러올수 없다!!!
그런데 _app.js 는 예외임 불러올수 있어
왜냐고? 내가 global 이니깐!!