Skip to content

Commit

Permalink
Improve api error handling in posting comment
Browse files Browse the repository at this point in the history
  • Loading branch information
marshallku committed Sep 19, 2024
1 parent 537b633 commit 877f5ac
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 17 deletions.
15 changes: 12 additions & 3 deletions apps/blog/src/api/instance.client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import httpClient, { HTTPClient } from "#utils/httpClient";
import { to } from "@marshallku/utils";

export const request: HTTPClient<unknown> = httpClient({
baseUrl: process.env.NEXT_PUBLIC_API_URL,
Expand All @@ -11,13 +12,21 @@ export const request: HTTPClient<unknown> = httpClient({
cache: "no-store",
interceptors: {
async response(response) {
try {
return await response.json();
} catch {
const [error, body] = await to(response.json());

if (error) {
// eslint-disable-next-line no-console
console.error("Failed to parse response body as JSON.");
return null;
}

if (!response.ok) {
// eslint-disable-next-line no-console
console.error(body);
throw new Error(body.message);
}

return body;
},
},
});
40 changes: 27 additions & 13 deletions apps/blog/src/components/CommentForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { FormEventHandler, useCallback, useRef, useState } from "react";
import { MutateOptions } from "@tanstack/react-query";
import Typography from "@marshallku/ui/Typography";
import Input from "@marshallku/ui/Input";
import Textarea from "@marshallku/ui/Textarea";
Expand All @@ -9,19 +10,27 @@ import { classNames } from "@marshallku/utils";
import { type CommentRequest } from "#api";
import CommentAvatar from "#components/CommentAvatar";
import styles from "./index.module.scss";
import { toast } from "@marshallku/toast";

interface CommentFormProps {
slug: string;
submit(data: CommentRequest): void;
submit(data: CommentRequest, options?: MutateOptions<unknown, Error, CommentRequest, unknown>): void;
isClientSide?: boolean;
}

const cx = classNames(styles, "comment-form");

function CommentForm({ slug, submit }: CommentFormProps) {
function CommentForm({ slug, submit, isClientSide = false }: CommentFormProps) {
const [name, setName] = useState("");
const [body, setBody] = useState("");
const formRef = useRef<HTMLFormElement>(null);

const reset = useCallback(() => {
formRef.current?.reset();
setName("");
setBody("");
}, []);

const handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(
(event) => {
event.preventDefault();
Expand All @@ -30,17 +39,15 @@ function CommentForm({ slug, submit }: CommentFormProps) {
const body = formData.get("body");

if (!body || typeof body !== "string" || body.trim() === "") {
return {
message: "내용을 입력해 주세요.",
};
toast("내용을 입력해 주세요.");
return;
}

const korean = /[\u3131-\uD79D]/giu;

if (!korean.test(body)) {
return {
message: "한글을 입력해 주세요.",
};
toast("한글을 입력해 주세요.");
return;
}

const data = {
Expand All @@ -53,12 +60,19 @@ function CommentForm({ slug, submit }: CommentFormProps) {
parentCommentId: formData.get("parentCommentId") as string,
};

submit(data);
formRef.current?.reset();
setName("");
setBody("");
if (isClientSide) {
submit(data, {
onSuccess: reset,
onError: (error) => {
toast(error.message);
},
});
} else {
submit(data);
reset();
}
},
[slug, submit],
[slug, isClientSide, submit, reset],
);

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/blog/src/components/PostCommentForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface PostCommentFormProps {

function PostCommentForm({ slug }: PostCommentFormProps) {
const { mutate } = usePostComment(slug);
return <CommentForm slug={slug} submit={mutate} />;
return <CommentForm slug={slug} submit={mutate} isClientSide />;
}

export default PostCommentForm;

1 comment on commit 877f5ac

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual regression test result - success

Component Story Success Viewport MisMatch Percentage
components-button string-children phone 0.00%
components-button string-children tablet 0.09%
input-input default phone 0.00%
input-input default tablet 0.00%
input-input line phone 0.00%
input-input line tablet 0.00%
input-input box phone 0.00%
input-input box tablet 0.00%
input-textarea line phone 0.00%
input-textarea line tablet 0.00%
input-textarea box phone 0.00%
input-textarea box tablet 0.00%
typography-typography default phone 0.00%
typography-typography default tablet 0.00%

Please sign in to comment.