Server Action And Mutations
- server action을 실행하면 현재 경로로 네트워크 POST 요청이 실행됩니다.
useOptimistic(실험 기능) + server action
useOptimistic + useTransition을 이용한 UI 동시성 처리
'use client';
import { useOptimistic, useTransition } from 'react';
import {
AccordionPanel,
AspectRatio,
Button,
Flex,
Input,
InputGroup,
InputRightElement,
Text,
} from '@chakra-ui/react';
import {
IndividualInquiryRetrieveType,
IndividualReplyType,
} from '@/swagger/@types/data-contracts';
import ImageAsNext from '@/components/ImageAsNext';
import { MyPageTranslations } from '@/containers/MyPage/MyPage';
import { AnswerIcon } from '@/icons';
import { createReply } from '../actions/create-reply';
import useQnaReplyForm from '../hooks/useQnaReplyForm';
interface QnaDetailProps {
data: IndividualInquiryRetrieveType | undefined;
qnaTranslations: MyPageTranslations['main']['qna'];
}
const QnaDetail = ({ data, qnaTranslations }: QnaDetailProps) => {
const {
handleSubmit,
reset,
register,
formState: { isDirty },
} = useQnaReplyForm();
const [isPending, startTransition] = useTransition();
const [optimisticReplies, addOptimisticReplies] = useOptimistic(
// 초기 데이터 설정
data?.replySet,
(
state: IndividualReplyType[] | undefined,
newReply: IndividualReplyType,
) => {
if (state) {
state.push(newReply);
return [...state];
}
return [newReply];
},
);
const onSubmit = handleSubmit((res) => {
if (!data) return;
startTransition(async () => {
// useOptimistic에서 반환한 addOptimisticReplies 로 낙관 업데이트 가능
// 사용자의 작업을 실시간 반영
addOptimisticReplies({
id: optimisticReplies ? optimisticReplies[0].id + 1 : 0,
isAdmin: false,
body: res.reply,
createdAt: res.createdAt,
});
reset();
await createReply({
data: {
individualInquiry: data.id,
body: res.reply,
},
});
});
});
return (
<AccordionPanel p="8px 16px" minH="65px">
<Flex direction="column">
{/* 답변 */}
{data?.inquiryState === 2 && (
<Flex direction="column">
{optimisticReplies?.map(({ id, isAdmin, body }) => {
return (
<Flex
key={reply.id}
p={{ base: '0 0 20px', sm: '0 16px 20px' }}
gap="8px"
>
<AnswerIcon boxSize="24px" fill="none" />
{isAdmin && (
<Text color="fanRed.500" textStyle="Body1_E">
{qnaTranslations.reply.admin}
</Text>
)}
<Text textStyle="Body1_R" whiteSpace="pre">
{body}
</Text>
</Flex>
);
})}
</Flex>
)}
</Flex>
</AccordionPanel>
);
};
export default QnaDetail;
server action과 react api들을 조합해서 사용했을 때 UI 동시성 처리에 용이합니다.
server actions와 함께 useActionState, useFormStatus를 사용하면 react-hook-form을 대체할 수 있을까?
useActionState와 useFormStatus를 사용하면 자바스크립트가 실행되기 이전에 폼과 상호작용 하도록 할 수 있다는 큰 장점이 있습니다.
useActionState를 통하여 초기 상태 및 업데이트된 상태 표시가 가능하며, server action을 통한 응답 결과를 통해서 성공 및 에러 상태 표시가 가능합니다. 또한 useFormStatus의 pending을 통한 button disabled 및 loading 처리 또한 가능합니다.
위의 훅과 서버액션 조합을 사용하면 Core Web Vital 중 INP 수치가 향상되어 SEO에 좋은 영향을 줄 것 같습니다.
하지만 react-hook-form에서 제공하는 isValid, isDirty 등의 상태는 직접 구현해야 할 것으로 보이며 이벤트 핸들러 기반의 즉각적인 validation을 해야 할 경우라면 react-hook-form을 대체하긴 어려워 보입니다.
서버액션을 사용할 때 react에서 제공하는 API인 useTransition useOptimistic 등의 훅을 함께 사용하여 UI 동시성 처리가 가능하여 유저 경험을 향상할 수 있습니다.
서버액션은 내 현재 경로로 POST 요청이 가기 때문에 필요시에만 사용하는 것을 권장합니다.
📌 Only plain objects can be passed to Client Components from Server Components ⇒ server action의 반환값은 plain objects 이어야 합니다. 응답 전문을 그대로 클라이언트로 넘기면 안 됩니다.
'Next.js' 카테고리의 다른 글
Next.js에서 React Server Component의 렌더링 방식 알아보기 (0) | 2024.06.25 |
---|---|
Next.js에서 fetch와 tanstack-query 효율적으로 사용하기 (0) | 2024.06.23 |
Next.js에서 Data Fetching & Caching 알아보기 (0) | 2024.06.19 |