React는 페이지를 컴포넌트로 분해하여 관리할 수 있게 한다. 그리고 이러한 컴포넌트들은 재사용할 수 있기 때문에 매우 효율적이다.
Next.js에 헤더나 네비게이션 바, 푸터와 같이 모든 페이지에서 재사용되는 컴포넌트를 레이아웃으로 적용하고 싶다면 어떻게 해야할까?
먼저, children
속성으로 고정되지 않고 변할 메인 구역을 받는 레이아웃 컴포넌트를 만든다.
*children: 부모 컴포넌트가 자식 컴포넌트를 감싸는 태그 안에 작성한 모든 것을 나타내는 특수한 속성
// components/layout.js
import NavigationBar from './navbar'
import Footer from './footer'
export default function Layout({ children }) {
return (
<>
<NavigationBar /> // 모든 페이지에 있는 네비게이션 바
<main>{children}</main>
<Footer /> // 모든 페이지에 있는 푸터
</>
)
}
props.children
로 받아서 할 수도 있다.
// components/layout.js
import NavigationBar from './navbar'
import Footer from './footer'
export default function Layout({ props }) {
return (
<>
<NavigationBar />
<main>{props.children}</main>
<Footer />
</>
)
}
_app.js
파일에서 Component
컴포넌트를 Layout
컴포넌트로 감싸준다(wrapping).
// pages/_app.js
import Layout from '../components/layout'
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
Show Details 버튼을 클릭하면 세부 페이지로 이동하도록 하려고 한다.
이때 useRouter
훅의 push
메소드를 이용할 수 있다.
router.push - Next.js
router.push([경로])
import Card from '../ui/Card';
import classes from './MeetupItem.module.css';
import { useRouter } from 'next/router';
function MeetupItem(props) {
const router = useRouter(); // useRouter 훅 호출
function showDetailHandler() {
router.push('/' + props.id); // 'http://localhost:3000/[props.id] 경로로 이동한다.
}
return (
<li className={classes.item}>
<Card>
<div className={classes.image}>
<img src={props.image} alt={props.title} />
</div>
<div className={classes.content}>
<h3>{props.title}</h3>
<address>{props.address}</address>
</div>
<div className={classes.actions}>
<button onClick={showDetailHandler}>Show Details</button> // 이벤트 핸들러 등록
</div>
</Card>
</li>
);
}
export default MeetupItem;
컴포넌트 별로 스타일을 주기 위해서는 [컴포넌트명].module.css
라는 이름으로 CSS 파일을 만들면 된다.
이 방식은 CSS 스타일의 유효범위를 해당 React 컴포넌트로만 제한하기 때문에 클래스 이름의 충돌(중복)을 방지할 수 있고, 스타일 규칙을 컴포넌트 단위로 캡슐화할 수 있다.
CSS 파일을 classes라는 이름으로 import 한다. (다른 변수명 사용 가능)
이때 classes는 JavaScript 객체가 되고, CSS 파일에서 정의한 모든 CSS 클래스를 이 객체의 프로퍼티로 사용할 수 있다.
그래서 여러 컴포넌트에서 같은 CSS 클래스를 사용하더라도 충돌없이 사용할 수 있다.
// MeetupDetail.js
import React from 'react';
import classes from './MeetupDetail.module.css'; // 다른 변수명 사용 가능
function MeetupDetail(props) {
return (
<section className={classes.detail}> // 객체의 프로퍼티로 접근할 수 있다.
<img src={props.image} alt={props.title} />
<h1>{props.title}</h1>
<address>{props.address}</address>
<p>{props.description}</p>
</section>
);
}
export default MeetupDetail;
/* MeetupDetail.module.css */
.detail {
text-align: center;
}
.detail img {
border-radius: 15px;
width: 100%;
}
지은님 덕분에 정리가 잘되는거같아요! 화이팅입니다