tanstack react-form antd示例

卓能文發表於2024-08-22
import { useForm } from "@tanstack/react-form";
import { zodValidator } from "@tanstack/zod-form-adapter";
import { z } from "zod";
import type { FieldApi } from "@tanstack/react-form";
import { Button, Input, Radio } from "antd";

function FieldInfo({ field }: { field: FieldApi<any, any, any, any> }) {
	return (
		<div>
			{field.state.meta.isTouched && field.state.meta.errors.length ? (
				<em style={{ color: "red" }}>{field.state.meta.errors.join(",")}</em>
			) : null}
			{field.state.meta.isValidating ? "Validating..." : null}
		</div>
	);
}

export default function App() {
	const form = useForm({
		defaultValues: {
			title: "",
			type: "本科",
		},
		onSubmit: async ({ value }) => {
			// Do something with form data
			console.log(value);
		},
		// Add a validator to support Zod usage in Form and Field
		validatorAdapter: zodValidator(),
	});

	return (
		<div>
			<h1>Zod Form Example</h1>
			<form
				onSubmit={(e) => {
					e.preventDefault();
					e.stopPropagation();
					form.handleSubmit();
				}}
			>
				<div>
					{/* A type-safe field component*/}
					<form.Field
						name="title"
						validators={{
							onChange: z.string().min(6, "至少6個字元"),
						}}
					>
						{(field) => {
							// Avoid hasty abstractions. Render props are great!
							return (
								<div>
									<Input
										id={field.name}
										name={field.name}
										value={field.state.value}
										onBlur={field.handleBlur}
										onChange={(e) => field.handleChange(e.target.value)}
										placeholder="論文標題"
									/>
									<FieldInfo field={field} />
								</div>
							);
						}}
					</form.Field>
				</div>
				<div>
					<form.Field name="type">
						{(field) => (
							<div>
								<Radio.Group
									id={field.name}
									name={field.name}
									onBlur={field.handleBlur}
									onChange={(e) => field.handleChange(e.target.value)}
									value={field.state.value}
								>
									<Radio value="大專">大專</Radio>
									<Radio value="本科">本科</Radio>
									<Radio value="碩士">碩士</Radio>
									<Radio value="博士">博士</Radio>
								</Radio.Group>
								<FieldInfo field={field} />
							</div>
						)}
					</form.Field>
				</div>
				<form.Subscribe
					selector={(state) => [state.canSubmit, state.isSubmitting]}
				>
					{([canSubmit, isSubmitting]) => (
						<Button type="primary" disabled={!canSubmit} htmlType="submit">
							{isSubmitting ? "..." : "提交"}
						</Button>
					)}
				</form.Subscribe>
			</form>
		</div>
	);
}

相關文章