提交带有验证的表单
Submit form with validation
我正在编写此代码以使用 React 和 Typescript 提交表单,并且 Material-UI:
export default function OpenTicket(props: any) {
const classes = useStyles();
const formHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log(e.target);
};
return (
<Container>
<Box m={5}>
<div className={classes.root}>
<form>
<TextField
id="outlined-full-width"
label="Name"
/>
<Button
variant="contained">
Submit
</Button>
</form>
</div>
</Box>
</Container>
);
}
要求:
export interface TicketDTO {
title?: string;
}
export async function postTicket(): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(
`${baseUrl}/support/tickets/create`
);
}
实现字段验证并在按下提交按钮时进行调用的正确方法是什么?
为了回答您的评论,这是您通常使用 react-hook-form 的方式:
import { useForm } from "react-hook-form";
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
// This won't be run unless all the input validations are met.
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName", { required: true, maxLength: 20 })} />
{errors.firstName && <span>This field is required</span>}
<input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
{errors.lastName && <span>This field can't be a number</span>}
<input type="number" {...register("age", { min: 18, max: 99 })} />
{errors.age && <span>This needs to be between 18 and 99 range</span>}
<input type="submit" />
</form>
);
}
注册函数是处理验证的函数,您可以在此处阅读所有可用的验证。
https://react-hook-form.com/api/useform/register
我认为这消除了很多代码重复来处理使用反应状态的输入,而且它还使验证和与外部 UI 库的集成变得非常容易。
我有这个 sandbox 以防您想查看实际代码。
编辑:
要像您问题中的那样执行 post 请求,并使用您使用的输入,您可以执行如下操作:
import axios, { AxiosResponse } from "axios";
import { useForm } from "react-hook-form";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
// This generic will type the data response correctly.
// So the errors object and register function will infer the types of TicketDTO.
} = useForm<TicketDTO>();
// This won't be run unless all the input validations are met.
const onSubmit = async (data: TicketDTO) => {
// This console.log won't give errors
// console.log(data.title);
// This console.log will give typing errors
// console.log(data.randomValue);
try {
await postTicket(data);
} catch (err) {
console.log(err);
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("title", { required: true, maxLength: 20 })} />
{errors.title && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
这里的 sandbox 和 post 不工作,因为没有有效的基础 url,但它应该做你想做的。
编辑没有反应挂钩形式。
这个例子使用了反应状态,正如我提到的,还有更多工作要做,因为您必须自己进行验证。
import axios, { AxiosResponse } from "axios";
import React from "react";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
// You will have to define your custom fields in separate states or one object state. this uses a separate state per input.
const [title, setTitle] = React.useState("");
// You will have to define the errors as well.
const [errors, setErrors] = React.useState<TicketDTO>({
title: ""
});
const onChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setTitle(event.target.value);
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
// Prevents browser to load the document
event.preventDefault();
// Here you will have to do logic to handle all your inputs.
if (title) {
try {
await postTicket({ title });
} catch (err) {
console.error(err);
}
setErrors({ title: "" });
} else {
setErrors({ title: "Title is required" });
}
};
return (
<form onSubmit={onSubmit}>
<input name="title" value={title} onChange={onChange} />
{errors.title && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
如果您不想在 React 中进行验证,也可以利用 HTML5 本机 validations。所以这只是一个这样做的问题:
import axios, { AxiosResponse } from "axios";
import React from "react";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
const [title, setTitle] = React.useState("");
const onChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setTitle(event.target.value);
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
// Prevents browser to load the document
event.preventDefault();
try {
await postTicket({ title });
} catch (err) {
console.error(err);
}
};
return (
<form onSubmit={onSubmit}>
{/* required prop makes usage of native html5 validation */}
<input name="title" value={title} required onChange={onChange} />
<input type="submit" />
</form>
);
}
我正在编写此代码以使用 React 和 Typescript 提交表单,并且 Material-UI:
export default function OpenTicket(props: any) {
const classes = useStyles();
const formHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log(e.target);
};
return (
<Container>
<Box m={5}>
<div className={classes.root}>
<form>
<TextField
id="outlined-full-width"
label="Name"
/>
<Button
variant="contained">
Submit
</Button>
</form>
</div>
</Box>
</Container>
);
}
要求:
export interface TicketDTO {
title?: string;
}
export async function postTicket(): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(
`${baseUrl}/support/tickets/create`
);
}
实现字段验证并在按下提交按钮时进行调用的正确方法是什么?
为了回答您的评论,这是您通常使用 react-hook-form 的方式:
import { useForm } from "react-hook-form";
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
// This won't be run unless all the input validations are met.
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName", { required: true, maxLength: 20 })} />
{errors.firstName && <span>This field is required</span>}
<input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} />
{errors.lastName && <span>This field can't be a number</span>}
<input type="number" {...register("age", { min: 18, max: 99 })} />
{errors.age && <span>This needs to be between 18 and 99 range</span>}
<input type="submit" />
</form>
);
}
注册函数是处理验证的函数,您可以在此处阅读所有可用的验证。
https://react-hook-form.com/api/useform/register
我认为这消除了很多代码重复来处理使用反应状态的输入,而且它还使验证和与外部 UI 库的集成变得非常容易。
我有这个 sandbox 以防您想查看实际代码。
编辑:
要像您问题中的那样执行 post 请求,并使用您使用的输入,您可以执行如下操作:
import axios, { AxiosResponse } from "axios";
import { useForm } from "react-hook-form";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
const {
register,
handleSubmit,
formState: { errors }
// This generic will type the data response correctly.
// So the errors object and register function will infer the types of TicketDTO.
} = useForm<TicketDTO>();
// This won't be run unless all the input validations are met.
const onSubmit = async (data: TicketDTO) => {
// This console.log won't give errors
// console.log(data.title);
// This console.log will give typing errors
// console.log(data.randomValue);
try {
await postTicket(data);
} catch (err) {
console.log(err);
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("title", { required: true, maxLength: 20 })} />
{errors.title && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
这里的 sandbox 和 post 不工作,因为没有有效的基础 url,但它应该做你想做的。
编辑没有反应挂钩形式。
这个例子使用了反应状态,正如我提到的,还有更多工作要做,因为您必须自己进行验证。
import axios, { AxiosResponse } from "axios";
import React from "react";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
// You will have to define your custom fields in separate states or one object state. this uses a separate state per input.
const [title, setTitle] = React.useState("");
// You will have to define the errors as well.
const [errors, setErrors] = React.useState<TicketDTO>({
title: ""
});
const onChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setTitle(event.target.value);
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
// Prevents browser to load the document
event.preventDefault();
// Here you will have to do logic to handle all your inputs.
if (title) {
try {
await postTicket({ title });
} catch (err) {
console.error(err);
}
setErrors({ title: "" });
} else {
setErrors({ title: "Title is required" });
}
};
return (
<form onSubmit={onSubmit}>
<input name="title" value={title} onChange={onChange} />
{errors.title && <span>This field is required</span>}
<input type="submit" />
</form>
);
}
如果您不想在 React 中进行验证,也可以利用 HTML5 本机 validations。所以这只是一个这样做的问题:
import axios, { AxiosResponse } from "axios";
import React from "react";
import "./styles.css";
interface TicketDTO {
title: string;
}
async function postTicket(
data: TicketDTO
): Promise<AxiosResponse<TicketDTO[]>> {
return await axios.post<TicketDTO[]>(`baseUrl/support/tickets/create`);
}
export default function App() {
const [title, setTitle] = React.useState("");
const onChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setTitle(event.target.value);
const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
// Prevents browser to load the document
event.preventDefault();
try {
await postTicket({ title });
} catch (err) {
console.error(err);
}
};
return (
<form onSubmit={onSubmit}>
{/* required prop makes usage of native html5 validation */}
<input name="title" value={title} required onChange={onChange} />
<input type="submit" />
</form>
);
}