如何在 React Hook Form v7 中使用软验证(又名提示或警告消息)

问题描述 投票:0回答:2

我正在尝试做的事情:

我正在构建一个复杂的表单,需要一种方法来根据某些条件(主要是正则表达式)提供提示和警告消息,而不阻止表单提交。本质上,这些消息将充当一种软验证形式,以帮助用户完成更高质量的表单。我想找到一个与 React Hook Form V7 配合良好的解决方案。

问题:

React Hook Form V7 仅支持硬验证(又名阻止表单提交)。据我所知,根据此 rhf 功能请求,没有计划在不久的将来添加此功能的支持。

可能的解决方案:

上述 rhf 功能请求中提出了一些 V6 解决方案,例如 rhf 创建者的这个:

    const PowerController = (props: Props) => {
      const { formState } = useFormContext();
      const isDirty = !!formState.dirtyFields[props.name];
      const isTouched = !!formState.touched[props.name];
      return (
        <Controller
          control={props.control}
          name={props.name}
          defaultValue={props.defaultValue}
          render={(innerProps) => {
            return props.render({
              ...innerProps,
              isDirty,
              isTouched,
              warning: props.warn(innerProps.value)
            });
          }}
        />
      );
    };
  • 但是,我无法让它与 V7 控制器一起工作

我还找到了关于如何使用 rhf 触发自定义 onChange 的答案,建议是将

onChange
传递给
Controller
useWatch()
链接在这里

  • 我喜欢将自定义

    onChange
    传递给
    Controller
    解决方案,但如果我理解正确,这样做将取代
    onChange
    中内置的
    Controller
    。我不确定如何进行这项工作,因为我只是想添加一些功能(又名字段更改的软验证)。

  • 使用 useWatch() 的解决方案来查看值何时发生变化,然后有一个单独的

    useEffect()
    ,我将软验证逻辑放入其中似乎很合理,但复杂的形式可能会变得非常混乱??

我需要什么帮助:

任何有关哪种方法最好的建议和/或有关如何调整电源控制器 V6 解决方案以与V7控制器配合使用的想法,我们将不胜感激。我刚刚学习 rhf,希望在我花几周时间用头撞墙试图解决这个问题之前得到一些输入,哈哈。

reactjs react-hook-form
2个回答
4
投票

我也遇到了同样的问题,发现重构提议的codesandbox解决方案以与rhf v7一起使用并不难(升级版本时的沙箱消息实际上很有帮助。

这是一个分叉版本,希望对您有所帮助 -

https://codesandbox.io/s/extend-controller-forked-v7-upgrade-iyw5p0?file=/src/App.tsx


0
投票

我设法让 PowerController 工作,但是,它不符合我们的需求,因为我们使用了 useController 钩子。

为了实现与提供的 PowerController 示例相同的功能,我编写了一个自定义挂钩。

import { FieldValues, FieldPath, UseControllerProps, UseControllerReturn, useController } from "react-hook-form";


type UsePowerControllerProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = UseControllerProps<TFieldValues, TName> & {
  warn: (value: string) => boolean | string;
}

type UsePowerControllerReturn<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = UseControllerReturn<TFieldValues, TName> & {
  warning: string | boolean
}

/**
 * Custom hook to work with controlled component, this function provide you with both form and field level state. Re-render is isolated at the hook level.
 *
 * @remarks
 * [API](https://react-hook-form.com/docs/usecontroller) • [Demo](https://codesandbox.io/s/usecontroller-0o8px)
 *
 * @param props - the path name to the form field value, and validation rules.
 *
 * @returns field properties, field and form state. {@link UsePowerControllerReturn}
 *
 * @example
 * ```tsx
 * function Input(props) {
 *   const { field, fieldState, formState } = usePowerController(props);
 *   return (
 *     <div>
 *       <input {...field} placeholder={props.name} />
 *       <p>{fieldState.isTouched && "Touched"}</p>
 *       <p>{formState.isSubmitted ? "submitted" : ""}</p>
 *     </div>
 *   );
 * }
 * ```
 */
export function usePowerController<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
  props: UsePowerControllerProps<TFieldValues, TName>,
): UsePowerControllerReturn<TFieldValues, TName> {
  const { field, fieldState, formState } = useController(props);


  return { field, fieldState, formState, warning: props.warn(field.value) }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>

以及如何使用挂钩;

const {
        field
        fieldState: { error },
        warning,
    } = usePowerController({
        name: 'yourField',
        control: control,
        
        warn: (value: any) => {
            // do some soft validation here
            return false;
        },
    });

如果您有任何改进,请告诉我!

© www.soinside.com 2019 - 2024. All rights reserved.