【问题标题】:React Hook Form with AntD Styling使用 AntD 样式的 React Hook 表单
【发布时间】: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-formantd支持不受控制的组件,就像我在第一条评论中提到的那样。

标签: reactjs react-hooks antd react-hook-form


【解决方案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
      猜你喜欢
      • 2021-04-03
      • 2022-10-25
      • 1970-01-01
      • 2021-03-29
      • 2020-06-06
      • 1970-01-01
      • 2020-05-22
      • 2020-03-08
      • 1970-01-01
      相关资源
      最近更新 更多