使用 AntD 样式的 React Hook 表单
Posted
技术标签:
【中文标题】使用 AntD 样式的 React Hook 表单【英文标题】:React Hook Form with AntD Styling 【发布时间】:2020-03-01 08:54:04 【问题描述】:我正在尝试弄清楚如何将 react-hook-form 与 antd 前端一起使用。
我已经制作了这个表单,它似乎可以正常工作(它是多部分表单向导的第 1 部分),只是没有显示错误消息。
谁能看到我在合并这两个表单系统时做错了什么?
我没有收到任何错误,但我认为我已要求两个表单字段都必须填写,但如果我在未完成的情况下按提交,则不会显示错误消息。
import React from "react";
import useForm from "react-hook-form";
import BrowserRouter as Router, Route from "react-router-dom";
import StateMachineProvider, createStore from "little-state-machine";
import withRouter from "react-router-dom";
import useStateMachine from "little-state-machine";
import updateAction from "./updateAction";
import Button, Form, Input, Divider, Layout, Typography, Skeleton, Switch, Card, Icon, Avatar from 'antd';
const Content = Layout
const Text, Paragraph = Typography;
const Meta = Card;
createStore(
data:
);
const General = props =>
const register, handleSubmit, errors = useForm();
const action = useStateMachine(updateAction);
const onSubit = data =>
action(data);
props.history.push("./ProposalMethod");
;
return (
<div>
<Content
style=
background: '#fff',
padding: 24,
margin: "auto",
minHeight: 280,
width: '70%'
>
<Form onSubmit=handleSubmit(onSubit)>
<h2>Part 1: General</h2>
<Form.Item label="Title" >
<Input
name="title"
placeholder="Add a title"
ref=register( required: true )
/>
errors.title && 'A title is required.'
</Form.Item>
<Form.Item label="Subtitle" >
<Input
name="subtitle"
placeholder="Add a subtitle"
ref=register( required: true )
/>
errors.subtitle && 'A subtitle is required.'
</Form.Item>
<Form.Item>
<Button type="secondary" htmlType="submit">
Next
</Button>
</Form.Item>
</Form>
</Content>
</div>
);
;
export default withRouter(General);
【问题讨论】:
当你有内置的getFieldDecorator
时为什么要使用第三方验证器,另外,你假设这种适用于html
组件的钩子将适用于自定义组件,如Form
,@ 987654325@等等。
什么意思?我试图使用带有钩子的 antd 样式。我想不通,所以我放弃了,现在使用带有钩子形式的常规 css。
我不明白带钩子的样式与您的要求有何关系
我想你是在问我为什么要尝试使用 antd。这就是为什么 - 样式与应用程序的其余部分一致。仅供参考:它不起作用,因为 antd 不支持不受控制的组件
我没问你为什么用antd,我问你为什么用react-hook-form
,antd
支持不受控制的组件,就像我在第一条评论中提到的那样。
【参考方案1】:
关于编写这样的代码:
<Input
name="subtitle"
placeholder="Add a subtitle"
ref=register( required: true )
/>
您假设 Input
引用绑定到 input
,但事实并非如此。
其实你需要绑定到inputRef.input
。
你可以用下面的代码检查一下:
const App = () =>
const inputRef = useRef();
const inputRefHtml = useRef();
useEffect(() =>
console.log(inputRef.current);
console.log(inputRefHtml.current);
);
return (
<FlexBox>
<Input ref=inputRef />
<input ref=inputRefHtml />
</FlexBox>
);
;
# Logs
Input props: Object, context: Object, refs: Object, updater: Object, saveClearableInput: function ()…
<input></input>
注意
antd
是一个完整的UI库(使用第3方“助手”应该“闯红灯”),特别是Form
实现了一个验证器,你可以看到a variety of examples in docs。
【讨论】:
【参考方案2】:react-hook-form 作者在这里。 Antd Input 组件并没有真正暴露内部ref
,所以你必须在useEffect
期间register
,并在onChange 期间更新值,例如:
const register, setValue = useForm();
useEffect(() =>
register( name: 'yourField' , required: true );
, [])
<Input name="yourField" onChange=(e) => setValue('yourField', e.target.value)
我已经构建了一个包装器组件,使 antd 组件集成更容易:https://github.com/react-hook-form/react-hook-form-input
import React from 'react';
import useForm from 'react-hook-form';
import RHFInput from 'react-hook-form-input';
import Select from 'react-select';
const options = [
value: 'chocolate', label: 'Chocolate' ,
value: 'strawberry', label: 'Strawberry' ,
value: 'vanilla', label: 'Vanilla' ,
];
function App()
const handleSubmit, register, setValue, reset = useForm();
return (
<form onSubmit=handleSubmit(data => console.log(data))>
<RHFInput
as=<Select options=options />
rules= required: true
name="reactSelect"
register=register
setValue=setValue
/>
<button
type="button"
onClick=() =>
reset(
reactSelect: '',
);
>
Reset Form
</button>
<button>submit</button>
</form>
);
【讨论】:
谢谢布鲁斯。不确定我是否遵循这个。来自 antd 的错误消息适用于多步骤表单的第一步,但不适用于后续步骤。如果我发现了什么,我会继续尝试并更新此页面。 你想在我们的频谱频道发布这个问题吗?我很乐意在那里提供帮助。 如果要触发验证,setValue('xxx', value, true) 网站上都有记录 谢谢@Bruce - 我会再试一次。 这现在是 RHF 内置的,所以你应该使用 Controller 组件来包装它。【参考方案3】:如果有人仍然对接近 Ant 提供的表单输入的默认样式感兴趣,下面是我如何让它工作的:
import Form, Button, Input from 'antd';
import useForm, Controller from 'react-hook-form';
function MyForm()
const control, handleSubmit, errors, setValue = useForm();
const emailError = errors.email && 'Enter your email address';
const onSubmit = data => console.log(data) ;
const EmailInput = (
<Form.Item>
<Input
type="email"
placeholder="Email"
onChange=e => setValue('email', e.target.value, true)
onBlur=e => setValue('email', e.target.value, true)
/>
</Form.Item>
);
return (
<form onSubmit=handleSubmit(onSubmit)>
<Controller
as=EmailInput
name="email"
control=control
defaultValue=""
rules=
required: true
validateStatus=emailError ? 'error' : ''
help=emailError
/>
<Button block type="primary" htmlType="submit">
Submit
</Button>
</form>
);
Codesandbox sample
【讨论】:
感谢分享-今晚我会看看这个。我仍在努力解决这个问题。【参考方案4】:这是我的工作方法:
const Example = () =>
const control, handleSubmit, errors = useForm()
const onSubmit = data => console.log(data)
console.log(errors)
return (
<Form onSubmit=handleSubmit(onSubmit)>
<Controller
name="email"
control=control
rules= required: "Please enter your email address"
as=
<Form.Item
label="name"
validateStatus=errors.email && "error"
help=errors.email && errors.email.message
>
<Input />
</Form.Item>
/>
<Button htmlType="submit">Submit</Button>
</Form>
)
【讨论】:
【参考方案5】:在 Ant Design v4.x + react-hook-form v6.x 中。我们可以正常实现
import useForm, Controller, SubmitHandler from 'react-hook-form';
import * as yup from 'yup';
import yupResolver from '@hookform/resolvers/yup';
import useIntl from 'react-intl';
import Input, Button, Form from 'antd';
const SignInSchema = yup.object().shape(
email: yup.string().email().required(),
password: yup.string().required('required').min(6, 'passwordMin'),
);
interface PropTypes
defaultValues?:
email: string;
password: string;
;
handleFormSubmit: SubmitHandler< email: string; password: string >;
function SignInForm( defaultValues, handleFormSubmit : PropTypes)
const intl = useIntl();
const handleSubmit, control, errors = useForm(
defaultValues,
resolver: yupResolver(SignInSchema),
);
return (
<Form onFinish=handleSubmit(handleFormSubmit)>
<Form.Item
validateStatus=errors && errors['email'] ? 'error' : ''
help=errors.email?.message
>
<Controller
as=Input
name="email"
autoComplete="email"
control=control
placeholder=intl.formatMessage( id: 'AUTH_INPUT_EMAIL' )
/>
</Form.Item>
<Form.Item
validateStatus=errors && errors['password'] ? 'error' : ''
help=errors.password?.message
>
<Controller
as=Input
name="password"
type="password"
control=control
autoComplete="new-password"
defaultValue=""
placeholder=intl.formatMessage( id: 'AUTH_INPUT_PASSWORD' )
/>
</Form.Item>
<Button type="primary" htmlType="submit">
intl.formatMessage( id: 'SIGN_IN_SUBMIT_BUTTON' )
</Button>
</Form>
);
export default SignInForm;
【讨论】:
嗨,在 Form.Item 中添加 validateStatus 和帮助道具时,我收到错误 index.js:1 警告:在 StrictMode 中不推荐使用 findDOMNode。 findDOMNode 被传递了一个 DomWrapper 的实例,它位于 StrictMode 中。相反,直接将 ref 添加到要引用的元素。在此处了解有关安全使用 refs 的更多信息:reactjs.org/link/strict-mode-find-node。请让我知道如何解决它。非常感谢! @ĐặngKiên 这是 Antd 设计的问题,他们可能需要在下一个版本中进行较大的更改以修复此问题github.com/ant-design/ant-design/issues/27921以上是关于使用 AntD 样式的 React Hook 表单的主要内容,如果未能解决你的问题,请参考以下文章