mirror of
https://github.com/vercel/next-learn.git
synced 2026-06-11 09:51:47 +00:00
Replace useFormStatus and useFormState with useActionState (#748)
This commit is contained in:
committed by
GitHub
parent
deca7c766f
commit
de76b00263
@@ -24,7 +24,6 @@ const FormSchema = z.object({
|
||||
const CreateInvoice = FormSchema.omit({ id: true, date: true });
|
||||
const UpdateInvoice = FormSchema.omit({ date: true, id: true });
|
||||
|
||||
// This is temporary
|
||||
export type State = {
|
||||
errors?: {
|
||||
customerId?: string[];
|
||||
|
||||
@@ -10,14 +10,14 @@ import {
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { Button } from '@/app/ui/button';
|
||||
import { createInvoice, State } from '@/app/lib/actions';
|
||||
import { useFormState } from 'react-dom';
|
||||
import { useActionState } from 'react';
|
||||
|
||||
export default function Form({ customers }: { customers: CustomerField[] }) {
|
||||
const initialState: State = { message: null, errors: {} };
|
||||
const [state, dispatch] = useFormState(createInvoice, initialState);
|
||||
const [state, formAction] = useActionState(createInvoice, initialState);
|
||||
|
||||
return (
|
||||
<form action={dispatch}>
|
||||
<form action={formAction}>
|
||||
<div className="rounded-md bg-gray-50 p-4 md:p-6">
|
||||
{/* Customer Name */}
|
||||
<div className="mb-4">
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/app/ui/button';
|
||||
import { updateInvoice, State } from '@/app/lib/actions';
|
||||
import { useFormState } from 'react-dom';
|
||||
import { useActionState } from 'react';
|
||||
|
||||
export default function EditInvoiceForm({
|
||||
invoice,
|
||||
@@ -21,10 +21,10 @@ export default function EditInvoiceForm({
|
||||
}) {
|
||||
const initialState: State = { message: null, errors: {} };
|
||||
const updateInvoiceWithId = updateInvoice.bind(null, invoice.id);
|
||||
const [state, dispatch] = useFormState(updateInvoiceWithId, initialState);
|
||||
const [state, formAction] = useActionState(updateInvoiceWithId, initialState);
|
||||
|
||||
return (
|
||||
<form action={dispatch}>
|
||||
<form action={formAction}>
|
||||
<div className="rounded-md bg-gray-50 p-4 md:p-6">
|
||||
{/* Customer Name */}
|
||||
<div className="mb-4">
|
||||
|
||||
@@ -9,13 +9,16 @@ import {
|
||||
} from '@heroicons/react/24/outline';
|
||||
import { ArrowRightIcon } from '@heroicons/react/20/solid';
|
||||
import { Button } from './button';
|
||||
import { useFormState, useFormStatus } from 'react-dom';
|
||||
import { useActionState } from 'react';
|
||||
|
||||
export default function LoginForm() {
|
||||
const [errorMessage, dispatch] = useFormState(authenticate, undefined);
|
||||
const [errorMessage, formAction, isPending] = useActionState(
|
||||
authenticate,
|
||||
undefined,
|
||||
);
|
||||
|
||||
return (
|
||||
<form action={dispatch} className="space-y-3">
|
||||
<form action={formAction} className="space-y-3">
|
||||
<div className="flex-1 rounded-lg bg-gray-50 px-6 pb-4 pt-8">
|
||||
<h1 className={`${lusitana.className} mb-3 text-2xl`}>
|
||||
Please log in to continue.
|
||||
@@ -61,7 +64,9 @@ export default function LoginForm() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LoginButton />
|
||||
<Button className="mt-4 w-full" aria-disabled={isPending}>
|
||||
Log in <ArrowRightIcon className="ml-auto h-5 w-5 text-gray-50" />
|
||||
</Button>
|
||||
<div
|
||||
className="flex h-8 items-end space-x-1"
|
||||
aria-live="polite"
|
||||
@@ -78,13 +83,3 @@ export default function LoginForm() {
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
function LoginButton() {
|
||||
const { pending } = useFormStatus();
|
||||
|
||||
return (
|
||||
<Button className="mt-4 w-full" aria-disabled={pending}>
|
||||
Log in <ArrowRightIcon className="ml-auto h-5 w-5 text-gray-50" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^5.0.1",
|
||||
"@types/react": "18.2.21",
|
||||
"@types/react-dom": "18.2.14",
|
||||
"@types/react": "18.3.3",
|
||||
"@types/react-dom": "18.3.0",
|
||||
"@vercel/style-guide": "^5.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.52.0",
|
||||
|
||||
133
dashboard/final-example/pnpm-lock.yaml
generated
133
dashboard/final-example/pnpm-lock.yaml
generated
@@ -59,11 +59,11 @@ devDependencies:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.2
|
||||
'@types/react':
|
||||
specifier: 18.2.21
|
||||
version: 18.2.21
|
||||
specifier: 18.3.3
|
||||
version: 18.3.3
|
||||
'@types/react-dom':
|
||||
specifier: 18.2.14
|
||||
version: 18.2.14
|
||||
specifier: 18.3.0
|
||||
version: 18.3.0
|
||||
'@vercel/style-guide':
|
||||
specifier: ^5.0.1
|
||||
version: 5.2.0(eslint@8.57.0)(prettier@3.3.2)(typescript@5.2.2)
|
||||
@@ -844,24 +844,19 @@ packages:
|
||||
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
|
||||
dev: true
|
||||
|
||||
/@types/react-dom@18.2.14:
|
||||
resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==}
|
||||
/@types/react-dom@18.3.0:
|
||||
resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
|
||||
dependencies:
|
||||
'@types/react': 18.2.21
|
||||
'@types/react': 18.3.3
|
||||
dev: true
|
||||
|
||||
/@types/react@18.2.21:
|
||||
resolution: {integrity: sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==}
|
||||
/@types/react@18.3.3:
|
||||
resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.12
|
||||
'@types/scheduler': 0.23.0
|
||||
csstype: 3.1.3
|
||||
dev: true
|
||||
|
||||
/@types/scheduler@0.23.0:
|
||||
resolution: {integrity: sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==}
|
||||
dev: true
|
||||
|
||||
/@types/semver@7.5.8:
|
||||
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||
dev: true
|
||||
@@ -1166,7 +1161,7 @@ packages:
|
||||
eslint-import-resolver-alias: 1.1.2(eslint-plugin-import@2.29.1)
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.2.2)
|
||||
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
|
||||
eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0)(eslint@8.57.0)
|
||||
@@ -1955,7 +1950,7 @@ packages:
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)
|
||||
eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0)
|
||||
eslint-plugin-react: 7.34.2(eslint@8.57.0)
|
||||
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0)
|
||||
@@ -1980,7 +1975,7 @@ packages:
|
||||
peerDependencies:
|
||||
eslint-plugin-import: '>=1.4.0'
|
||||
dependencies:
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
dev: true
|
||||
|
||||
/eslint-import-resolver-node@0.3.9:
|
||||
@@ -2004,7 +1999,7 @@ packages:
|
||||
enhanced-resolve: 5.17.0
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.5
|
||||
is-core-module: 2.13.1
|
||||
@@ -2027,7 +2022,7 @@ packages:
|
||||
enhanced-resolve: 5.17.0
|
||||
eslint: 8.57.0
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0)
|
||||
fast-glob: 3.3.2
|
||||
get-tsconfig: 4.7.5
|
||||
is-core-module: 2.13.1
|
||||
@@ -2039,6 +2034,36 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: '*'
|
||||
eslint-import-resolver-node: '*'
|
||||
eslint-import-resolver-typescript: '*'
|
||||
eslint-import-resolver-webpack: '*'
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
eslint:
|
||||
optional: true
|
||||
eslint-import-resolver-node:
|
||||
optional: true
|
||||
eslint-import-resolver-typescript:
|
||||
optional: true
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.2.2)
|
||||
debug: 3.2.7
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -2138,6 +2163,41 @@ packages:
|
||||
ignore: 5.3.1
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.2.2)
|
||||
array-includes: 3.1.8
|
||||
array.prototype.findlastindex: 1.2.5
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.fromentries: 2.0.8
|
||||
object.groupby: 1.0.3
|
||||
object.values: 1.2.0
|
||||
semver: 6.3.1
|
||||
tsconfig-paths: 3.15.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -2173,41 +2233,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
|
||||
resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.2.2)
|
||||
array-includes: 3.1.8
|
||||
array.prototype.findlastindex: 1.2.5
|
||||
array.prototype.flat: 1.3.2
|
||||
array.prototype.flatmap: 1.3.2
|
||||
debug: 3.2.7
|
||||
doctrine: 2.1.0
|
||||
eslint: 8.57.0
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.13.1
|
||||
is-glob: 4.0.3
|
||||
minimatch: 3.1.2
|
||||
object.fromentries: 2.0.8
|
||||
object.groupby: 1.0.3
|
||||
object.values: 1.2.0
|
||||
semver: 6.3.1
|
||||
tsconfig-paths: 3.15.0
|
||||
transitivePeerDependencies:
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint@8.57.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
||||
@@ -55,7 +55,9 @@ export default function LoginForm() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<LoginButton />
|
||||
<Button className="mt-4 w-full">
|
||||
Log in <ArrowRightIcon className="ml-auto h-5 w-5 text-gray-50" />
|
||||
</Button>
|
||||
<div className="flex h-8 items-end space-x-1">
|
||||
{/* Add form errors here */}
|
||||
</div>
|
||||
@@ -63,11 +65,3 @@ export default function LoginForm() {
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
function LoginButton() {
|
||||
return (
|
||||
<Button className="mt-4 w-full">
|
||||
Log in <ArrowRightIcon className="ml-auto h-5 w-5 text-gray-50" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
|
||||
const nextConfig = {};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user