Learning Log/Next.js

[next.js] 생활코딩 Next.js 13 2일차

자척개 2023. 8. 4. 01:19
반응형

* 범위 : 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

반응형