브라우저에서 호출 할 수 있는 서버에서 실행되는 비동기 함수
서버액션을 활용하면 api를 만들필요없이 함수 하나만으로 브라우저에서 Next 서버측에서 실행되는 함수를 직접 호출할 수 있다.
특정 폼 특정 양식에서 사용
export default function Page() {
const saveName = async (formData: FormData) => {
"use server";
console.log(formData)
const name = formData.get("name");
await sql`INSERT INTO Names (name) VALUES (${name})`; //sql문
await saveDB({ name:name}); // DB에 저장
}
return (
<form action={saveName}>
<input name="name" placeholder="이름을 입력해주세요" />
<button type="submit">제출하기</button>
</form>
)
}
서버에서만 실행되는 함수를 브라우저가 직접 호출하면서 데이터까지 formData로 전달할 수 있게 해주는 기능 - 기존에서 api를 사용했어야했는데 js만으로도 가능해졌다.
api를 사용하려면 경로, 예외처리 등등 손이 많이간다.
단순한 기능을 사용할 때 코드가 간결해진다.
브라우저가 아닌 오직 서버만 실행되어 보안상으로 민감한거나 중요한 데이터를 다룰때 유용
입력 내용이 화면에 바로 반영되어야 할 경우 보통 input을 통해 데이터를 전달하면 바로 적용이 되지 않고 새로고침을 해야 반영이 된다. 이를 해결하기 위해 재검증 구현이 필요하다.
데이터가 입력이 되면 재랜더링을 통해 재검증이 되어야한다.
import { revalidatePath } from "next/cache";
try {
...
revaliatePath('경로')
}
next 캐시에서 revalidatePath를 불러오고 불러온 경로에 페이지를 인수로 전달한다.
그러면 인수로 전달한 페이지를 재검증한다.
revalidatePath는 next 서버에게 인수로 전달한 경로의 페이지를 다시 생성(재검증)해달라는 메소드
revaliatePath('경로')
revaliatePath("경로/폴더경로", "page")
폴더경로나 파일의 경로를 명시
revaliatePath('/경로', "layout")
레이아웃을 재검증
revaliatePath('/', "layout")
import { revalidateTag } from "next/cache";
revaliateTag('태그명')
태그 값을 갖는 데이터 캐시 재검증
태그는 데이터 페칭에 적용되는 옵션에 태그를 지정해준다.
지정해준 태그를 활용하여 재검증을 한다.
import 해주어야함
const response = await fetch(
`api 주소`,
{ next: { tags : ['태그명']} }
)
태그 방식이 불필요한 캐시를 삭제하지 않고 가능하다.
import { useActionState } from "react";
export default funtcion Page () {
const [state, formAction, isPending] = useActionState(
createReviewAction,
null
);
}
useActionState는 리액트 19 버전에서 출시
폼 태그의 상태를 쉽게 다룰 수 있는 기능이 있다.
그러면 전달받을 form의 액션 값을 formAction으로 설정해 실행시켜주면 useActionState 훅이 인수로 전달한 createReviewAction을 실행. 자동으로 state와 pending 값을 관리
createReviewAction.ts
export default funtcion createReviewAction () {
if (!bookId || !content || !author) {
return {
status: false,
error: "내용을 입력해주세요",
};
}
}
특정 서버액션 조건에서 반환된 값을 사용할 수 있다.
특정 조건으로 action이 실패했다면
status로 액션이 실패했음을 알려주고 error 프로퍼티로 실패 이유를 알려줄 수 있다.
추가로 try catch문에서도 실패 시 반환값을 전달할 수 있다.
<input disabled={isPending}/>
useEffect(() => {
if (state && !state.status) {
alert(state.error);
}
}, [state]);
위 처럼 input의 제어할 수 있고 아래처럼 state 값으로 상황에 맞는 에러메세지를 추가할 수도 있다.