* 범위 : 8~12
* 8. css
global.css 파일에 아래와 같이 코드 작성
h1 a {
text-decoration: none;
}
* 9. backend
- json server를 사용해 백엔드 구축
npx json-server --port 9999 --watch db.json
- db.json에 아래와 같은 형식으로 db 추가할 수 있음
"topics": [
{ "id": 1, "title": "html", "body": "html is ..." },
{ "id": 2, "title": "css", "body": "css is ..." }
],
- 크롬 개발자도구에서 콘솔을 통해 통신하려면, fetch문을 사용해 통신할 수 있음
fetch('http://localhost:9999/topics').then((res)=>{return resp.json()}).then(result=>{console.log('result', result)});
=> 네트워크 탭에서 통신되는 모습 확인 가능
* 10. 글목록 가져오기
- server component와 client component
- 그동안 구현하던 방식은 client component였음, 그치만 server component도 react에 있던 개념
- 언제 server component를 사용할까? 사용자와 상호작용이 하지 않는 컴포넌트인 경우 => ssr할 때와 동일
- 언제 client component를 사용할까? 사용자와 상호작용하는 컴포넌트인 경우 => csr할 때와 동일
1) server component => client component로 변경하기
- next.js는 기본적으로 component를 server component로 간주함
=> 그냥 바로 useState 같은 걸 쓰면 에러
=> 에러 해결하려면 해당 컴포넌트 최상단에 "use client"라고 적어줘야 함
=> 그리고 또 발생하는 에러는 server client에서 사용하는 metadata 때문에 발생, meta data 부분은 일단 주석 처리
- 장점 : 사용자와 상호작용이 많은 경우 로딩 속도 빠름
"use client";
import Link from "next/link";
import "./globals.css";
import { useEffect, useState } from "react";
// export const metadata = {
// title: "Web tutorials",
// description: "Generated by jung",
// };
export default function RootLayout({ children }) {
const [topics, setTopics] = useState([]);
useEffect(() => {
fetch("http://localhost:9999/topics")
.then((res) => {
return res.json();
})
.then((result) => {
setTopics(result);
});
}, []);
return (
<html>
<body>
<h1>
<Link href="/">WEB</Link>
</h1>
<ol>
{topics.map((topic) => {
return (
<li key={topic.id}>
<Link href={`/read/${topic.id}`}>{topic.title}</Link>
</li>
);
})}
</ol>
{children}
<ul>
<li>
<Link href="/create">Create</Link>
</li>
<li>
<Link href="/update/1">Update</Link>
</li>
<li>
<input type="button" value="delete" />
</li>
</ul>
</body>
</html>
);
}
2) client component => server component로 변경하기
- useEffect 대신 async 선언하기(async-await 방식으로 동기 처리)
- 장점 : 용량이 적음, 초기 로딩 빠름, js disabled시키고 reload해도 정상 작동
import Link from "next/link";
import "./globals.css";
export const metadata = {
title: "Web tutorials",
description: "Generated by jung",
};
export default async function RootLayout({ children }) {
const resp = await fetch("http://localhost:9999/topics");
const topics = await resp.json();
return (
<html>
<body>
<h1>
<Link href="/">WEB</Link>
</h1>
<ol>
{topics.map((topic) => {
return (
<li key={topic.id}>
<Link href={`/read/${topic.id}`}>{topic.title}</Link>
</li>
);
})}
</ol>
{children}
<ul>
<li>
<Link href="/create">Create</Link>
</li>
<li>
<Link href="/update/1">Update</Link>
</li>
<li>
<input type="button" value="delete" />
</li>
</ul>
</body>
</html>
);
}
* 11. 글 읽기
- 사용자와 상호작용 없는 페이지이기 때문에 server component로 진행
export default async function Read(props) {
const resp = await fetch(`http://localhost:9999/topics/${props.params.id}`);
const topic = await resp.json();
return (
<>
<h2>{topic.title}</h2>
{topic.body}
</>
);
}
* 12. 글 생성
- 상호작용이 있는 페이지이기 때문에 client component로 진행
"use client";
import { useRouter } from "next/navigation";
export default function Create() {
const router = useRouter();
return (
<form
onSubmit={(e) => {
e.preventDefault();
const title = e.target.title.value;
const body = e.target.body.value;
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title, body }),
};
fetch(`http://localhost:9999/topics`, options)
.then((res) => res.json())
.then((result) => {
console.log(result);
const lastId = result.id;
// router를 통해 방금 생성한 글로 리디렉션 가능
router.push(`/read/${lastId}`);
});
}}
>
<p>
<input type="text" name="title" placeholder="title" />
</p>
<p>
<textarea name="body" placeholder="nody"></textarea>
</p>
<p>
<input type="submit" value="create" />
</p>
</form>
);
}
파일 지우고 뭔가 에러있을 때 일단 국룰은 서버 껐켜하기
그래도 안되는 경우 .next 폴더 지우고 다시 만들기
rm -rf .next
npm run dev
'Learning Log > Next.js' 카테고리의 다른 글
[next.js] 생활코딩 Next.js 13 3일차 (0) | 2023.08.08 |
---|---|
[next.js] 생활코딩 Next.js 13 1일차 (0) | 2023.08.03 |
[next.js] 원티드 프리온보딩 챌린지 사전과제 (0) | 2023.07.03 |