[英]React Hook Form : how to set a field as required when a value of another field is 'TEST'
[英]Support callback for changing another field value when using React Hook Form validation
這有效: https://codesandbox.io/s/stoic-beaver-ucydi
使用 React Hook Form 重構后,這不起作用: https://codesandbox.io/s/objective-cloud-bkunr?file=/src/ControlledTextField.tsx
我最近使用Fluent UI和自定義組件中的包裝字段構建了一個有狀態的 React 表單。
我已經包含了一個功能,當您在網站標題字段中鍵入時,會生成網站 URL 字段中的值(在我的例子中,它只是復制字段值並刪除對 URL 無效的字符)。
(簡化的)代碼運行良好,看起來像這樣:
import * as React from 'react';
import {useState} from 'react';
import { PrimaryButton } from 'office-ui-fabric-react';
import SiteTitleField from '../../../common/formFields/SiteTitleField';
import SiteUrlField from '../../../common/formFields/SiteUrlField';
export default function MyForm(props) {
const urlPrefix: string = "https://" + window.location.hostname + "/sites/";
const [siteTitle, setSiteTitle] = useState();
const [titleErrorMessage, setTitleErrorMessage] = useState('');
const [siteUrl, setsiteUrl] = useState();
const [urlErrorMessage, setUrlErrorMessage] = useState('');
function handleTitleChange(e) {
if (e.target.value.length) {
setTitleErrorMessage('');
} else {
setTitleErrorMessage('This field is required.');
}
setSiteTitle(e.target.value);
setsiteUrl(e.target.value.replace(/[^A-Za-z0-9_-]/g, ""));
}
function handleUrlChange(e) {
if (e.target.value.length) {
setUrlErrorMessage('');
} else {
setUrlErrorMessage('This field is required.');
}
setsiteUrl(e.target.value);
}
function handleButtonClick(e) {
// call to API
}
return (
<SiteTitleField
siteTitle={siteTitle}
titleErrorMessage={titleErrorMessage}
handleTitleChange={handleTitleChange}
/>
<SiteUrlField
siteUrl={siteUrl}
urlErrorMessage={urlErrorMessage}
urlPrefix={urlPrefix}
handleUrlChange={handleUrlChange}
/>
<PrimaryButton
text="Create a Request"
onClick={handleButtonClick}
/>
);
}
SiteTitleField 組件:
import * as React from 'react';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
export default function SiteTitleField(props) {
return (
<TextField
value={props.siteTitle}
required
aria-required="true"
errorMessage={props.titleErrorMessage}
label="Site Title"
placeholder="Set the title of the site"
onChange={props.handleTitleChange}
/>
);
}
SiteUrlField 組件:
import * as React from 'react';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
export default function SiteUrlField(props) {
return (
<TextField
value={props.siteUrl}
required
aria-required="true"
errorMessage={props.urlErrorMessage}
label="Site URL"
prefix={props.urlPrefix}
placeholder="Set site URL alias"
onChange={props.handleUrlChange}
/>
);
}
現在我正在嘗試使用 React Hook Form 和 Yup 驗證模式重構我的表單。
我用 React Hook Form Controller 組件及其渲染屬性包裝了 Fluent UI TextField 組件:
import * as React from 'react';
import { Control, Controller, FieldErrors } from "react-hook-form";
import { TextField } from 'office-ui-fabric-react';
export interface IControlledTextFieldProps {
control: Control<any>;
name: string;
errors: FieldErrors<any>;
label?: string;
prefix?: string;
placeholder?: string;
onChangeCallback?: (...event: any[]) => void;
refValue?: string;
}
export const ControlledTextField: React.FC<IControlledTextFieldProps> = ({
control,
name,
errors,
label,
prefix,
placeholder,
onChangeCallback,
refValue,
}) => {
return (
<Controller
name={name}
control={control}
disabled={disabled}
render={({ onChange, onBlur, value, name: fieldName }) => (
<TextField
onChange={(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) => {onChange(refValue); onChangeCallback && onChangeCallback(event);}}
value={refValue}
onBlur={onBlur}
name={fieldName}
errorMessage={errors[fieldName] && errors[fieldName].message}
label={label}
prefix={prefix}
placeholder={placeholder}
/>
)}
/>
);
};
我相應地替換了 SiteTitleField 和 SiteUrlField 的代碼,並添加了一個簡單的 Yup 驗證模式:
const schema = yup.object().shape({
siteTitle: yup.string().required("Site Title needs to be provided."),
siteUrl: yup.string().required("Site URL needs to be provided."),
});
const { handleSubmit, errors, control } = useForm<Inputs>({
resolver: yupResolver(schema)
});
我用<form>
標簽包裝了表單並相應地更改了字段屬性:
<form onSubmit={handleSubmit(handleButtonClick)}>
<SiteTitleField
name="siteTitle"
control={control}
errors={errors}
handleTitleChange={handleTitleChange}
/>
<SiteUrlField
name="siteUrl"
control={control}
errors={errors}
siteUrl={siteUrl}
urlPrefix={urlPrefix}
/>
<PrimaryButton
text="Create a Request"
type="submit"
/>
</form>
關於 state 我只留下了值復制需要的東西:
const [siteUrl, setsiteUrl] = useState();
function handleTitleChange(e) {
setsiteUrl(e.target.value.replace(/[^A-Za-z0-9_-]/g, ""));
}
我無法同時進行 React Hook 表單驗證和我的值復制功能。
使用此代碼時,驗證效果很好但用戶無法編輯 Site URL 字段:
onChange={(event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>, newValue?: string) => {onChange(refValue); onChangeCallback && onChangeCallback(event);}}
value={refValue}
或復制和編輯字段值效果很好,但即使輸入了值,驗證也會說兩個字段都是空的(必填),當使用此代碼時:
onChange={onChangeCallback}
value={refValue}
好的,我明白了。
而不是使用 state 來更新字段值
const [siteUrl, setsiteUrl] = useState();
function handleTitleChange(e) {
setsiteUrl(e.target.value.replace(/[^A-Za-z0-9_-]/g, ""));
}
我應該使用useForm
的setValue
:
const {
handleSubmit,
errors,
control,
setValue // added
} =
useForm<Inputs>({
resolver: yupResolver(schema)
});
function handleTitleChange(e) {
// changed:
setValue("siteUrl", e.target.value.replace(/[^A-Za-z0-9_-]/g, ""), {
shouldValidate: true
});
}
並且ControlledTextField
中的value
應該簡單地解析為:
value={value}
工作解決方案: https://codesandbox.io/s/focused-montalcini-ehbp3?file=/src/App.tsx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.