function ChangeName({ name, setName }) {
const [error, submitAction, isPending] = useActionState(
async (previousState, formData) => {
const error = await updateName(formData.get("name"));
if (error) return error;
redirect("/path");
return null;
},
null,
);
return (
<form action={submitAction}>
<input type="text" name="name" />
<button type="submit" disabled={isPending}>Update</button>
{error && <p>{error}</p>}
</form>
);
}
위에서 본 것 처럼 useActionState
는 input으로 비동기 Callback을 받고, Tuple로 3가지의 값을 반환합니다. Input으로 받는 Callback은 submitAction이 실행되어질 때에 호출되는 로직입니다. 이전값과 입력받은 값을 사용합니다. 이 Callback에서 반환하는 값을 useActionState의 첫 번째 인자인 error로 사용됩니다. 마지막으로 isPending은 Callback의 비동기가 완료되어질 때까지 True 상태를 가집니다.
이 useActionState
는 <form />
태그와 함께 사용되며, 기존에 useState와 useTransition을 사용하던 방식으로 사용할 수 있습니다.
const { pending, data, method, action } = useFormStatus();
useFormStatus는 사용자가 폼을 제출하는 동안 사용할 수 있는 값을 반환합니다. 각 값은 아래와 같은 의미가 있습니다.
- pending: Type은 boolean이며, dl 제출이 진행중인 경우 true를 반환합니다. 그렇지 않으면 false를 반환합니다.
- data: Type은 object이며, 제출한 데이터를 담고 있는 객체입니다. 제출이 진행중이거나 dl이 없으면 null을 반환합니다.
- method: Type은 string이며, 제출하는 Method를 나타냅니다. 기본값은 GET입니다. 이 값은 사용자가 제출할 때 필요한 Method을 지정할 수 있습니다.
- action: Type은 function이며, 제출하는 동안 사용할 수 있는 Action입니다. 이 값은 사용자가 제출할 때 필요한 Action을 지정할 수 있습니다.
아래와 같이 사용할 수 있습니다.
import { useFormStatus } from "react-dom";
function Submit() {
const { pending, action } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Submitting..." : "Submit"}
</button>
);
}
function Form({ action }) {
return (
<form action={action}>
<Submit />
</form>
);
}
export default function App() {
return <Form action={action} />;
}
function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);
const submitAction = async formData => {
const newName = formData.get("name");
setOptimisticName(newName);
const updatedName = await updateName(newName);
onUpdateName(updatedName);
};
return (
<form action={submitAction}>
<p>Your name is: {optimisticName}</p>
<p>
<label>Change Name:</label>
<input
type="text"
name="name"
disabled={currentName !== optimisticName}
/>
</p>
</form>
);
}
useOptimistic은 일반적으로 async action이 진행중일 때 다른 상태를 표시할 떄 사용합니다. 말 그대로, 비동기 함수가 종료되기 전에 낙관적으로 복사된 상태를 보여줍니다.
function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}
function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
<Suspense fallback={<div>Loading...</div>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
)
}
이 use 훅은 Promise를 resolve하고, 값을 반환하도록 합니다. 이 Promise가 resolve 되는 동안에는 를 표시합니다.
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
//...
<MyInput ref={ref} />
이제 Custom Component에서도 ref props를 그냥 사용할 수 있습니다. 😋
이제 hydration errors의 위치를 정확하게 Console에서 확인할 수 있습니다.