New Sep 18, 2024

React-hook-form: how to add logic to the onChange property in a custom input

Libraries, Frameworks, etc. All from Newest questions tagged reactjs - Stack Overflow View React-hook-form: how to add logic to the onChange property in a custom input on stackoverflow.com

I am working in a project using react with typescript, and I'm using react-hook-form and the form component that comes with shadcn/ui: https://ui.shadcn.com/docs/components/input#form For my case, I created a custom Input component which has a button inside of it (with a pen icon), which will toggle on and off the **readonly **property of the input, but i want to add another functionality:

The problem is that the onChange property doesn't work on the input to get the value or just to set a state indicating that the value has been changed to replace the buttons, and when I tried to isolate the input by using react-hook-form's hooks such as useFormContext to get the **control ** prop and then pass it as well as the name of the input to the useWatch or useFormState, it triggers countless re-renders. If anyone has any idea or suggestion please help me. Here is the code of my component if anyone wants to modify it:

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> )}

/>

Scroll to top