Nextjs

생성 기능 구현 - Client component

생성 기능을 구현하기 위해서는 onSubmit과 같은 사용자와 상호작용하는 코드가 필요합니다. 이런 코드는 서버 쪽에서 실행할 수 없기 때문에 클라이언트 쪽으로 전송되어서 실행되야 합니다. 여기서는 클라이언트 컴포넌트를 만드는 방법을 살펴봅니다. 

소스코드

https://github.com/egoing/nextapp/commit/0a316f1e31a52729607bc190d5c5e65483a71e20

절차

1. app/create/layout.js 삭제

이 파일은 중첩된 layout을 보여주기 위해서 만든 임시 파일이기 때문에 삭제 합니다. 

2. app/create/page.js 수정

'use client'
 
import { useRouter } from "next/navigation";
 
export default function Create(){
  const router = useRouter();
  return <form onSubmit={async evt=>{
    evt.preventDefault();
    const title = evt.target.title.value;
    const body = evt.target.body.value;
    const resp = await fetch('http://localhost:9999/topics/', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({title, body})
    });
    const topic = await resp.json();
    console.log("file: page.js:19 ~ Create ~ topic:", topic)
    router.push(`/read/${topic.id}`);
    router.refresh();
  }}>
    <h2>Create</h2>
    <p><input type="text" name="title" placeholder="title" /></p>
    <p><textarea name="body" placeholder="body"></textarea></p>
    <p><input type="submit" value="create" /></p>
  </form>
}

3.  server component -> client component

'use client'

위의 코드를 사용하면 client component로 전환됩니다. 클라이언트 컴포넌트가 되면 useEffect, useState, onSubmit과 같은 코드를 사용할 수 있게 됩니다. 

4. 라우터

const router = useRouter();

useRouter를 사용하면 라우터 객체를 생성할 수 있습니다. useRouter는 client component에서만 사용 가능합니다. 

5. 라우터 사용

router.push(`/read/${topic.id}`);
router.refresh();

router.push를 사용하면 페이지 리로드 없이 사용자의 화면을 해당 페이지로 이동합니다. router.refresh를 사용하면 서버 컴포넌트를 서버 쪽에서 다시 랜더링해서 새로 고침할 수 있습니다. 여기서는 app/layout.js을 새로고침하기 위해서 사용된 코드입니다.

6. cache 업데이트

router.refresh를 했음에도 글 목록이 갱신되지 않을 것입니다. 그 이유는 서버쪽에서 fetch를 사용하면 응답 결과를 저장하기 때문입니다. 개발 서버를 다시 시작하고, 페이지를 리로드한 후에 터미널을 봅시다. 

루트 페이지(/)로 접속했을 때 app/layout.js에서 fetch가 동작해서 http://localhost:3000/api/topics/로 접속이 발생했다는 뜻입니다. cache : MISS는 캐쉬가 없기 때문에 서버에 실제로 접속해서 데이터를 가져왔다는 뜻입니다. 

 다시 접속하면 아래와 같이 됩니다. 

cache : HIT 입니다. 캐쉬를 사용했다는 뜻입니다. 

캐쉬를 삭제한 후에 router.refresh를 하면 됩니다만, 그건 수업의 범위를 벗어나기 때문에 fetch를 하는 단계에서 캐쉬를 사용하지 않는 방법을 보여드리겠습니다. 자세한 내용은 revalidate를 확인해주세요.

7. app/layout.js 편집

import Link from 'next/link'
import './globals.css'
export const metadata = {
  title: 'WEB tutorial',
  description: 'Generated by egoing',
}
export default async function RootLayout({ children }) {
  const resp = await fetch('http://localhost:9999/topics/', {cache:'no-cache'}) 
  const topics = await resp.json();
  console.log('page/layout.js/topics', topics)
  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/id">update</Link></li>
          <li><button>delete</button></li>
        </ul>
      </body>
    </html>
  )
}

위의 코드는 아래 부분이 변경되었습니다. 

const resp = await fetch('http://localhost:9999/topics/', {cache:'no-cache'}) 

{cache:'no-cache'}를 추가하면 캐쉬를 사용하지 않게 됩니다. 

이제 layout.js의 fetch는 랜더링 될 때마다 캐쉬를 사용하지 않고 신선한 데이터를 가져오게 되었습니다. 

 

댓글

댓글 본문
버전 관리
egoing
현재 버전
선택 버전
graphittie 자세히 보기