[Next.js] 글 수정

DU·2024년 7월 8일

Next.js

목록 보기
14/16
post-thumbnail

글을 누르고 Update버튼을 누르면 404에러가 발생하는 상황입니다. 해당 글의 update를 구현하려면 app/src/update/[id]/page.js를 만들 것 입니다.

Update는 2가지 기능의 합성이라고 생각하면 쉬울 것 입니다.

1. Create
2. Read

기본적인 구조는 Create가 더 간편하기 때문에 Create의 구조를 가져오겠습니다.

"use client";

import { useRouter } from "next/navigation";

export default functionUpdate() {
  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();
        router.push(`/read/${topic.id}`);
        router.refresh();
      }}
    >
      <h2>Update</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>
  );
}

Update에는 원본이 적혀있어야 하기 때문에 Read 기능도 가지고 있는 것입니다.

Read페이지를 열어보았더니 현재 서버 컴포넌트로 사용이 불가능한 상황입니다.

"use client";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";

export default function Update(props) {
  const router = useRouter();
  const [title, setTitle] = useState(""); 
  const [body, setBody] = useState("");
  const id = props.params.id;
  async function refresh() {
    const resp = await fetch(`http://localhost:9999/topics/${id}`);
    const topic = await resp.json();
    setTitle(topic.title);
    setBody(topic.body);
  }
  useEffect(() => {
    refresh();
  }, []);
  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/${id}`, {
          method: "PATCH",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ title, body }),
        });
        const topic = await resp.json();
        router.push(`/read/${topic.id}`);
        router.refresh();
      }}
    >
      <h2>Update</h2>
      <p>
        <input
          type="text"
          name="title"
          placeholder="title"
          onChange={(e) => setTitle(e.target.value)} 
          value={title}
        />
      </p>
      <p>
        <textarea
          name="body"
          palceholder="body"
          onChange={(e) => setBody(e.target.value)}
          value={body}
        ></textarea>
      </p>
      <p>
        <input type="submit" value="update" />
      </p>
    </form>
  );
}
  • "use client"; : 클라이언트 컴포넌트로 바꿔야하기에 사용합니다.
  • const [title, setTitle] = useState("");: 글을 타이틀과 바디 폼에 넣기 위해 state만들었습니다. 그 후 각각의 value값에 값을 줍니다.
  • <input type="text" name="title" placeholder="title" onChange={(e) => setTitle(e.target.value)} value={title} />
    : 세팅된 타이틀의 값을 onChange를 통해 값이 바뀔 때마다 값을 바꾸도록 설정합니다.
  • method: "PATCH" : POST가 아니라 수정을 할때는 PUSH나 PATCH로 코딩해야합니다.

이렇게 해서 웹페이지를 통해 글을 수정할 때, 글의 제목과 내용의 첫글자를 대문자로 입력해도 표시되는 것은 소문자였습니다. 글 목록을 가져올 때 cache: HIT 인 것을 볼 수 있습니다. 그래서 상세보기 페이지에서 cach: : “no-store” 를 설정하였습니다.

export default async function Read(props) {
  const resp = await fetch(`http://localhost:9999/topics/${props.params.id}`, {
    cache: "no-store",
  });
  const topic = await resp.json();
  return (
    <>
      <h2>{topic.title}</h2>
      {topic.body}
    </>
  );
}

0개의 댓글