Skip to content

Commit

Permalink
fix: update React hooks for optimistic form submission
Browse files Browse the repository at this point in the history
  • Loading branch information
k70suK3-k06a7ash1 committed May 5, 2024
1 parent 730986f commit 3ab9db2
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 19 deletions.
40 changes: 21 additions & 19 deletions src/forms/Travel/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useOptimistic, useRef, useState } from "react";
import { useActionState, useOptimistic, useRef } from "react";
import { UseOptimisticStateForm } from "../UseOptimisticState";

const initDialogRef = (ref: HTMLDialogElement) => {
ref.showModal();
Expand All @@ -13,33 +14,34 @@ const deliverTitle = async (title: string) => {
};
export const TravelForm = () => {
const formRef = useRef<HTMLFormElement | null>(null);
const [title, setTitle] = useState("");
const [optimisticTitle, addOptimisticTitle] = useOptimistic<string, string>(
title,
const [title, setTitle] = useOptimistic<string, string>(
"",
(_currentState, optimisticValue) => optimisticValue
);

const sendTitle = async (formData: FormData) => {
const sentTitle = await deliverTitle(formData.get("title") as string);
setTitle(() => sentTitle);
};

const formAction = async (formData: FormData) => {
addOptimisticTitle(formData.get("title") as string);
formRef.current?.reset();
await sendTitle(formData);
};
const [response, submitAction, isPending] = useActionState<
string | null,
FormData
>(
async (_, formData) => {
const requestTitle = formData.get("title") as string;
setTitle(requestTitle);
await deliverTitle(requestTitle);
return requestTitle + "done";
},
null,
"/finished"
);

return (
<>
<dialog ref={initDialogRef}>
<form ref={formRef} action={formAction}>
optimatic : {optimisticTitle}
<div />
label : {title}
<UseOptimisticStateForm />
<form ref={formRef} action={submitAction}>
label : {isPending ? title : response}
<div />
<input name="title" type="text" />
<button type="submit">Submit</button>
{isPending && <p>Submitting...</p>}
</form>
</dialog>
</>
Expand Down
69 changes: 69 additions & 0 deletions src/forms/UseOptimisticActionState/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useActionState, useOptimistic } from "react";

type ReturnResponse = {
ok: boolean;
message?: string;
};

type FormYourNameProps = {
name: string;
};

async function updateName(props: FormYourNameProps): Promise<ReturnResponse> {
console.log(props);
await new Promise((resolve) => setTimeout(resolve, 1000));
if (props.name.length < 3) {
return {
ok: false,
message: "Name is too short",
};
}
return {
ok: true,
};
}

const parseFormData = (formData: FormData) => {
const name = formData.get("name") as string;
return {
name,
};
};

export const UseOptimisticActionStateForm = () => {
const [name, setName] = useOptimistic("name");
const [response, submitAction, isPending] = useActionState<
ReturnResponse | null,
FormData
>(
async (_, formData) => {
const props = parseFormData(formData);
setName(props.name);
const error = await updateName(props);
if (!error.ok) {
return error;
}
// redirect to /finished without 3rd argument
// redirect("/finished", RedirectType.push);
return null;
},
null,
// redirect to /finished
"/finished"
);

return (
<div>
<form action={submitAction}>
<p>Current Name: {name}</p>
<label>
New Name:
<input type="text" name="name" />
</label>
<button type="submit">Submit</button>
{isPending && <p>Submitting...</p>}
{response && <p>{response.message}</p>}
</form>
</div>
);
};
40 changes: 40 additions & 0 deletions src/forms/UseOptimisticState/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useOptimistic, useRef, useState } from "react";

const deliverTitle = async (title: string) => {
await new Promise((res) => setTimeout(res, 1000));
return title;
};
export const UseOptimisticStateForm = () => {
const formRef = useRef<HTMLFormElement | null>(null);

const [title, setTitle] = useState("");

const [optimisticTitle, addOptimisticTitle] = useOptimistic<string, string>(
title,
(_currentState, optimisticValue) => optimisticValue
);

const sendTitle = async (formData: FormData) => {
const sentTitle = await deliverTitle(formData.get("title") as string);
setTitle(() => sentTitle);
};

const formAction = async (formData: FormData) => {
addOptimisticTitle(formData.get("title") as string);
formRef.current?.reset();
await sendTitle(formData);
};

return (
<>
<form ref={formRef} action={formAction}>
optimatic : {optimisticTitle}
<div />
label : {title}
<div />
<input name="title" type="text" />
<button type="submit">Submit</button>
</form>
</>
);
};

0 comments on commit 3ab9db2

Please sign in to comment.