#TIL 3 모바일 청첩장 빌더 - Comment

김병훈·2024년 2월 23일
0

bora-n-maria

목록 보기
3/7
post-thumbnail

작업 내용

  1. Comment 삭제하기
    a. submit 후, post 데이터 업데이트하기
    b. 삭제 시, 비밀번호 체크하기
    c. 비밀번호 확인 가능하도록 하기
    d. 비밀번호 입력 후, submit 했을 때 저장하겠냐는 confirm 안뜨게 하기
  2. Comment 생성 로직 수정하기
    a. 비밀번호 입력 input 수정
    b. 값을 입력하지 않았을 때, submit이 실행되지 않도록 하기

1. Comment 삭제하기

Submit 후, post 데이터 업데이트하기

post 데이터는 서버 컴포넌트에서 fetch를 통해 가져왔기 때문에 revalidateTag를 이용해서 데이터를 업데이트시켜야 했다.
그런데, 클라이언트 함수에서 revalidateTag를 호출했을 때, 에러가 발생함.

const handleSubmit = async () => {
  // ...
  await fetch(url, { method: "DELETE" });
  revalidateTag("comments");
  // Invariant: static generation store missing in revalidateTag comments
}

클라이언트 컴포넌트에서 revalidate를 하는 방법을 알아봤다.
"How to revalidate data from the client Component"

이 질문의 답변 내용 중 "revalidate하는 함수를 serverAction으로 만들어라"라는 걸 보고 적용해봤다.

// actions.ts
const deleteComment = async (commentId: string, password: string) => {
  "use server";
  // host, protocol, url을 구하기
  await fetch(url, { method: "DELETE" });
  revalidateTag("comments");
}

// DeleteCommentDialog.tsx 중
const handleAction = async (formData: FormData) => {
  // ...
  await deleteComment(commentId, password);
}

알게된 내용
서버 액션은 서버 컴포넌트에서만 사용이 가능한 줄 알았지만, 아니었다.
하긴, 서버 컴포넌트도 어떻게 보면 서버 함수일텐데, 클라이언트 컴포넌트의 자식 컴포넌트로 렌더링을 할 수 있으니까.

삭제 시, 비밀번호 체크하기

  1. 비밀번호를 어떻게 전달할 것인가?
    DELETE 메서드는 body를 포함할 수는 있지만, 실제로 body를 사용하는 것을 권장하진 않는다고 한다. (경우에 따라서 body를 사용할 수 없는 케이스도 있기 때문)
    그렇다면, 어떻게 비밀번호를 포함해서 전달할까?
    -> QueryString에 비밀번호를 포함시켜서 전달하도록 함

  2. supabase로 삭제 요청을 보냈을 때, 실제로 삭제되었는지 판단하려면?
    eq 메서드로 id, password를 전달해서, 삭제요청을 보냈는데 id와 password가 일치하지 않는 케이스를 판단하려면 count를 활용할 수 있다.
    delete의 옵션에 count 로직을 어떻게 수행할 지 결정할 수 있다.
    count 옵션이 없으면 count가 null로 반환되고, 있으면 실제 삭제된 row의 수가 반환된다.

// comments/:id/route.ts
const DELETE = async () => {
  // ...
  const { count } = await supabase
    .from("comments")
    .delete({ count: "exact" })
    .eq("id", id)
    .eq("password", password);
}
  1. 한글 등이 포함되었을 때, 주소가 유효하도록 하려면?
    쿼리스트링을 encodeURIComponent 함수를 통해 인코딩시키기
const encodedPassword = encodeURIComponent(password)
const url = `${protocol}://${host}/api/comments/${commentId}?password=${encodedPassword}`
  1. sumit 시, 비밀번호 저장 여부를 체크하는 브라우저 dialog가 뜨지 않도록 하기
    비밀번호 input의 autoComplete 속성의 값을 one-time-code로 하면, confirm 창이 뜨지 않음.
<input
  type="password"
  autoComplete="one-time-code"
  />

Comment 생성 로직 수정하기

비밀번호 인풋 수정

  1. autoComplete 속성을 one-time-code로 설정하기

form submit 로직

  1. input 값을 입력하지 않았을 때, submit할 수 없도록 하기
    두 가지의 방식을 고민했었지만, b안으로 결정했음
    이유: a안으로 하려면, submit 버튼의 disabled를 막고 input에서의 Enter 키 입력도 막아줘야 했기 때문에 b안에 비해 로직이 복잡해질 것 같았음.
    -
    a. submit 이벤트를 실행할 수 없도록 막기
    b. submit 이벤트가 수행되었을 때 확인하여, 중단하기
    -

    입력한 값이 유효한지를 확인하는 것이니까, zod를 활용하면 좋겠다는 생각을 했음.
    지금은 입력했는지 여부만 판단하면 되는 것이기에 min 메서드를 활용했고, 추후에 다른 조건이 생기면 schema만 수정해주면 될 것 같다.
const createCommentSchema = z.object({
  name: z.string().min(1),
  content: z.string().min(1),
  password: z.string().min(1),
});

const handleFormAction = async (formData: FormData) => {
  // ...
  const data = {
    name,
    content,
    password,
  }
  const parsedData = createComentSchema.safeParse(data);
  
  if (!parsedData.success) {
    alert("입력값을 확인해주세요");
    return;
  }
};
profile
재밌는 걸 만드는 것을 좋아하는 메이커

1개의 댓글

comment-user-thumbnail
2024년 7월 18일

Dinosaur Game is a fascinating game that you can play anytime, anywhere, without the need for an internet connection, ensuring you are always entertained no matter where you are, whether it's on a long flight, a road trip, or simply in an area with no Wi-Fi.

답글 달기