리액트 공식 문서를 참고한 정리 내용 (25.08 기준)
form액션의 결과를 기반으로 State를 업데이트할 수 있게 제공한다.
useActionState는 기존의 폼 액션 함수와 초기 State를 전달받고, 폼에서 사용할 새로운 액션을 반환한다. 또한 최신 폼 State와 액션이 대기 중인지 여부(isPending)도 반환한다.
이떄 최신 폼 State는 useActionState에 전달한 함수에도 함께 전달된다.
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
fn폼이 제출되거나 버튼이 눌렀을 때 호출되는 함수
- 함수가 호출되면 첫 번째 인수로 폼의 이전 State(처음에 전달한
intialState, 이후에는 이전 반환값)가 전달되고, 그 뒤로는 폼 액션이 일반적으로 받는 인수들이 전달된다.
👉 즉, "폼이 실행될 때 무슨 일을 할지" 정해주는 함수
intialState👉 쉽게 말하면 “폼이 시작할 때 기본값”
permalink해당 폼이 수정하는 페이지 URL을 포함하는 문자열
permalink(고유한 URL)로 이동한다,👉 JS가 늦게 로드되더라도 페이지가 끊기지 않고 자연스럽게 동작하도록 도와주는 옵션이다.
다음 세 가지 값을 담은 배열을 반환한다.
initialState와 일치fn)가 실행되면, 그 반환값이 이 state로 바뀐다.👉 “폼의 현재 결과 상태”
form의 action prop이나 버튼의 formAction prop에 넣을 수 있는 함수이다.fn을 그냥 쓰는 게 아니라, useActionState가 상태랑 연결된 래퍼 함수를 돌려주는 거라고 보면 된다.startTransition 안에서 수동으로 직접 호출할 수 있다.👉 “폼 제출 시 실행할 액션 함수(상태랑 연결된 버전)”
###isPending (대기 중 여부)
isPending 플래그이다.👉 “폼 제출이 처리 중인지 알려주는 깃발”
import { useActionState } from "react";
async function increment(previousState, formData) {
return previousState + 1;
}
function StatefulForm({}) {
const [state, formAction] = useActionState(increment, 0);
return (
<form>
{state}
<button formAction={formAction}>Increment</button>
</form>
);
}
useActionState를 사용하면, Client는 자바스크립트 실행 전에도 폼과 상호작용할 수 있다.State와 동일하게 동작한다.useActionState에 전달된 함수는 첫 번째 인수로 이전 또는 초기 State를 추가로 받는다.💬
useActionState(fn, initialState)에 넣는fn은 첫 번째 인수로 이전 state를 무조건 받는다. 즉 ,fn(prevState, …기타 폼 데이터)
하지만 일반 폼 액션 함수를 사용하면 보통 첫 번째 인수가formData같은 데이터이다. 그래서useActionState를 사용할 때는 함수 정의 방식이 약간 달라진다.// 일반 폼 액션 async function submit(formData) { // formData만 받음 } // useActionState에서 쓰는 액션 async function submit(prevState, formData) { // 이전 state와 formData 모두 받음 }👉 서버 컴포넌트 환경에서는 JS 없이도 폼이 동작하고,
useActionState에 넘기는 함수는 첫 번째 인수로 이전 state를 받기 때문에 일반 폼 액션과 함수 모양이 조금 다르다.
import { useActionState } from "react";
import { addToCart } from "./actions.js";
function AddToCartForm({itemID, itemTitle}) {
const [message, formAction, isPending] = useActionState(addToCart, null);
return (
<form action={formAction}>
<h2>{itemTitle}</h2>
<input type="hidden" name="itemID" value={itemID} />
<button type="submit">Add to Cart</button>
{isPending ? "Loading..." : message}
</form>
);
}
export default function App() {
return (
<>
<AddToCartForm itemID="1" itemTitle="JavaScript: The Definitive Guide" />
<AddToCartForm itemID="2" itemTitle="JavaScript: The Good Parts" />
</>
);
}
"use server";
export async function addToCart(prevState, queryData) {
const itemID = queryData.get('itemID');
if (itemID === "1") {
return "Added to cart";
} else {
await new Promise(resolve => setTimeout(resolve, 2000));
return "Couldn't add to cart: the item is sold out.";
}
}
<form>의 action Prop에 전달하거나 startTransition 안에서 직접 호출할 수 있는 새로운 액션이다.