向简单的 React + Typescript 应用程序添加验证
Adding validation to simple React + Typescript application
我有一个简单的问题,但我被卡住了,因为我不太了解 TypeScript(我需要很快了解它)。
我必须在提交时添加简单的验证,这将检查值是否不为空。
我有最简单的 React 表单:
type FormValues = {
title: string;
};
function App() {
const [values, handleChange] = useFormState<FormValues>({
title: ""
});
const handleSubmit = (evt: FormEvent) => {
evt.preventDefault();
console.log("SUBMITTED");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
id="title"
name="title"
onChange={handleChange}
type="text"
value={values.title}
/>
<button type="submit">submit</button>
</form>
</div>
);
}
处理表单的自定义挂钩:
import { useCallback, useReducer } from "react";
type InputChangeEvent = {
target: {
name: string;
value: string;
};
};
function useFormState<T extends Record<string, string>>(initialValue: T) {
const [state, dispatch] = useReducer(
(prevState: T, { name, value }: InputChangeEvent["target"]) => ({
...prevState,
[name]: value
}),
initialValue
);
const handleDispatch = useCallback(
(evt: InputChangeEvent) => {
dispatch({
name: evt.target.name,
value: evt.target.value
});
},
[dispatch]
);
return [state, handleDispatch] as const;
}
export default useFormState;
现在我想在提交时添加简单的验证并且(因为 TS)我不知道如何做。我考虑了三个选项:
- 将验证逻辑放入
handleSubmit
方法。
- 将验证逻辑放入自定义
useFormState
挂钩中。
- 创建另一个自定义挂钩,仅用于管理验证。
我尝试处理此 CodeSandbox example 中的第一个(我认为是最差的)解决方案,但正如我所说,TS 类型比我强,代码不起作用。
有没有人能帮我解决这两种情况(选择最正确的解决方案,然后,运行 带 TS 的代码)?
一种常见的方法是将表单错误值存储在 React useState 变量中并根据需要呈现它。
const [error, setError] = React.useState('');
// ...
const handleSubmit = (evt: FormEvent) => {
evt.preventDefault();
// This might be the wrong way to check the input value
// I haven't worked directly with form submit events in a hot minute
if (!evt.target.value) {
setError('Title is required');
}
};
// ...
<input
id="title"
name="title"
onChange={handleChange}
type="text"
value={values.title}
aria-describedby="title-error"
required
aria-invalid={!!error}
/>
{error && <strong id="title-error" role="alert">{error}</strong>}
注意 aria-describedby
、required
、aria-invalid
和 role
属性对于加强输入及其错误之间的语义关系很重要,向屏幕宣布错误readers 当它出现时,并将输入指定为“必需”。
如果您在表单中有多个输入,您可以将 error
值放入一个对象中,该对象可以为表单的每个字段存储一个单独的错误:
const [errors, setErrors] = React.useState({});
// ...
setErrors(oldErrors => ({...oldErrors, title: "Title is required"}));
// ...
{errors.title && <strong id="title-error" role="alert">{errors.title}</strong>}
另一种常见模式是在修改或“修改”表单时清除输入错误以允许重新提交表单:
onChange={(e) => {
setError(''); // or setErrors(({title: _, ...restErrors}) => restErrors);
handleChange(e);
}}
请注意,所有这些错误处理逻辑 都可以 集成到您的自定义挂钩中以进行一般性的 form/input 处理,但并非必须如此。
我有一个简单的问题,但我被卡住了,因为我不太了解 TypeScript(我需要很快了解它)。
我必须在提交时添加简单的验证,这将检查值是否不为空。
我有最简单的 React 表单:
type FormValues = {
title: string;
};
function App() {
const [values, handleChange] = useFormState<FormValues>({
title: ""
});
const handleSubmit = (evt: FormEvent) => {
evt.preventDefault();
console.log("SUBMITTED");
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
id="title"
name="title"
onChange={handleChange}
type="text"
value={values.title}
/>
<button type="submit">submit</button>
</form>
</div>
);
}
处理表单的自定义挂钩:
import { useCallback, useReducer } from "react";
type InputChangeEvent = {
target: {
name: string;
value: string;
};
};
function useFormState<T extends Record<string, string>>(initialValue: T) {
const [state, dispatch] = useReducer(
(prevState: T, { name, value }: InputChangeEvent["target"]) => ({
...prevState,
[name]: value
}),
initialValue
);
const handleDispatch = useCallback(
(evt: InputChangeEvent) => {
dispatch({
name: evt.target.name,
value: evt.target.value
});
},
[dispatch]
);
return [state, handleDispatch] as const;
}
export default useFormState;
现在我想在提交时添加简单的验证并且(因为 TS)我不知道如何做。我考虑了三个选项:
- 将验证逻辑放入
handleSubmit
方法。 - 将验证逻辑放入自定义
useFormState
挂钩中。 - 创建另一个自定义挂钩,仅用于管理验证。
我尝试处理此 CodeSandbox example 中的第一个(我认为是最差的)解决方案,但正如我所说,TS 类型比我强,代码不起作用。
有没有人能帮我解决这两种情况(选择最正确的解决方案,然后,运行 带 TS 的代码)?
一种常见的方法是将表单错误值存储在 React useState 变量中并根据需要呈现它。
const [error, setError] = React.useState('');
// ...
const handleSubmit = (evt: FormEvent) => {
evt.preventDefault();
// This might be the wrong way to check the input value
// I haven't worked directly with form submit events in a hot minute
if (!evt.target.value) {
setError('Title is required');
}
};
// ...
<input
id="title"
name="title"
onChange={handleChange}
type="text"
value={values.title}
aria-describedby="title-error"
required
aria-invalid={!!error}
/>
{error && <strong id="title-error" role="alert">{error}</strong>}
注意 aria-describedby
、required
、aria-invalid
和 role
属性对于加强输入及其错误之间的语义关系很重要,向屏幕宣布错误readers 当它出现时,并将输入指定为“必需”。
如果您在表单中有多个输入,您可以将 error
值放入一个对象中,该对象可以为表单的每个字段存储一个单独的错误:
const [errors, setErrors] = React.useState({});
// ...
setErrors(oldErrors => ({...oldErrors, title: "Title is required"}));
// ...
{errors.title && <strong id="title-error" role="alert">{errors.title}</strong>}
另一种常见模式是在修改或“修改”表单时清除输入错误以允许重新提交表单:
onChange={(e) => {
setError(''); // or setErrors(({title: _, ...restErrors}) => restErrors);
handleChange(e);
}}
请注意,所有这些错误处理逻辑 都可以 集成到您的自定义挂钩中以进行一般性的 form/input 处理,但并非必须如此。