React-hook-form:如何向自定义输入中的 onChange 属性添加逻辑

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

我正在一个使用react with typescript的项目中工作,我正在使用react-hook-form和shadcn/ui附带的表单组件:https://ui.shadcn.com/docs/components/input#形式。 对于我的情况,我创建了一个自定义输入组件,其中有一个按钮(带有钢笔图标),它将打开和关闭输入的 readonly 属性,但我想添加另一个功能:

  • 当用户点击笔按钮修改输入的值时,我想一旦该输入的初始值发生变化,就用提交按钮替换该按钮,并且只有当他点击提交按钮并且表单提交时才可以对于每个输入,输入再次返回**只读**,依此类推。

问题是 onChange 属性不适用于输入来获取值或只是设置一个状态,指示值已更改以替换按钮,并且当我尝试使用 React 隔离输入时-hook-form 的钩子,例如 useFormContext 来获取 **control ** 属性,然后将其以及输入的名称传递给 useWatchuseFormState,它会触发无数次重新渲染。 如果有人有任何想法或建议请帮助我。 这是我的组件的代码,如果有人想修改它:

import * as React from "react";
import { Button } from "@/components/ui/button";
import { Input, type InputProps } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import { Pencil, PencilOff } from "lucide-react";

interface EditableInputProps extends InputProps {
     editPermission?: boolean;
}

const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>(
({ className, editPermission = true, ...props }, ref) => {
    const [canEdit, setCanEdit] = React.useState<boolean>(false);
    const disabled = props.disabled || !editPermission;

    const handleEdit = () => {
        if (!disabled) {
            setCanEdit((prev) => !prev);
        }
    };

    return (
        <div className="relative">
            <Input
                ref={ref}
                type="text"
                readOnly={!canEdit ? true : false}
                className={cn("pr-10", className)}
                {...props}
            />
            <Button
                type="button"
                variant="ghost"
                size="sm"
                className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
                disabled={disabled}
                onClick={() => handleEdit()}
            >
                {canEdit && !disabled ? (
                    <Pencil className="h-4 w-4" aria-hidden="true" />
                ) : (
                    <PencilOff className="h-4 w-4" aria-hidden="true" />
                )}
                <span className="sr-only">
                    {canEdit ? "Can edit input" : "Cannot edit input"}
                </span>
            </Button>
        </div>
    );
}
);

EditableInput.displayName = "EditableInput";
export { EditableInput };

// usage in my form
<FormField
control={form.control}
name="order_total"
render={({ field }) => (
    <FormItem>
        <FormLabel>
            Order Total
        </FormLabel>
        <FormControl>
            <EditableInput
                {...field}
                placeholder="Order Total"
            />
        </FormControl>
        <FormMessage />
    </FormItem>
)}
/>
reactjs typescript react-hook-form shadcnui
1个回答
0
投票

既然你可以访问 formContext,你应该能够做这样的事情。

const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>(
({ className, editPermission = true, ...props }, ref) => {

    const {formState, getValues, resetField} = useFormContext();

    const [canEdit, setCanEdit] = React.useState<boolean>(false);
    const disabled = props.disabled || !editPermission;

    const handleEdit = () => {

        const value = getValue(props.name)
         ....do something with the value....
        if (!disabled) {
            setCanEdit((prev) => !prev);
        }
       ...finally...
       resetField(props.name, {defaultValue:value})  // this should reset the dirty state and the default value for the field so dirty can be properly detected. 
       
    };

    const isDirty = formState.dirtyFields[props.name]

    return (
        <div className="relative">......


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