我正在一个使用react with typescript的项目中工作,我正在使用react-hook-form和shadcn/ui附带的表单组件:https://ui.shadcn.com/docs/components/input#形式。 对于我的情况,我创建了一个自定义输入组件,其中有一个按钮(带有钢笔图标),它将打开和关闭输入的 readonly 属性,但我想添加另一个功能:
问题是 onChange 属性不适用于输入来获取值或只是设置一个状态,指示值已更改以替换按钮,并且当我尝试使用 React 隔离输入时-hook-form 的钩子,例如 useFormContext 来获取 **control ** 属性,然后将其以及输入的名称传递给 useWatch 或 useFormState,它会触发无数次重新渲染。 如果有人有任何想法或建议请帮助我。 这是我的组件的代码,如果有人想修改它:
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>
)}
/>
既然你可以访问 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">......