I am trying to build a custom form component. In this I use inertiajs useForm hook to automatically load the data into a state (similar to react-use-form).
But my problem is, that everytime i type a letter (so basically i´m doing a stateupdate), my input field keeps losing its focus.
This is the offical inertiajs documentation: https://inertiajs.com/forms
My form component:
type FormField<T> ={
name: keyof T;
label: string;
type: "text" | "textarea";
group?: string;
}
interface Props<T extends Record<string, any>> {
initialData: T
fields: FormField<T>[]
}
export function Form<T extends Record<string, any>>(props: Props<T>) {
const { initialData, fields, formLayoutKey } = props;
const { data, setData, errors, patch } = useForm<T>((initialData ?? {}) as T);
const onSubmit = (e?: React.FormEvent) => {
e?.preventDefault();
console.log(data)
}
const renderFieldsByGroup = (group: string) => {
return fields
.filter((f) => f.group === group)
.map((field, index) => {
// hardcoded .name prop here, but doesnt affect problem
const value = data.name
const error = errors[field.name as string];
const key = `${index}-${field.name}`
switch (field.type) {
case 'text':
return (
<FieldSet key={key} label={field.label} error={error}>
{/* Hardcoded "name" here but doesnt affect problem */}
<Input
type="text"
placeholder={field.label}
data={value ?? ''}
onChange={e => setData("name", e.target.value)}
/>
</FieldSet>
);
default:
return null;
}
});
};
return (
<form onSubmit={onSubmit}>
<FormLayout>
<div key="general">
{renderFieldsByGroup("myGroup")}
</div>
</FormLayout>
</form>
);
}
as you can see, im trying to render my fields based on the field props. My custom input props looks like this:
interface Props {
type?: string
placeholder?: string
classes?: string
onChange?: (e: any) => void
data?: string
}
export default function Input(props: Props) {
const { type = "text", placeholder, classes, onChange, data} = props
return (
<input
type={type ?? "text"}
placeholder={placeholder}
className={`${type === "checkbox" ? "checkbox" : "input border"} ${classes}`}
onChange={onChange}
value={typeof data === "string" || typeof data === "number" ? data : ""}
checked={type === "checkbox" ? Boolean(data) : undefined}
/>
);
}
I checked, if the input Field have the same key - but this wasnt the case. Also the key isnt constantly changing.
I checked in my browser and it seems like the form / page gets rerendered every time I make an input. That explains why my focus keeps getting lost, but i dont know how to fix this.
After some trial and error, I have found the error, but cannot explain exactly why it occurs.
The error is actually caused by <FormLayout>
. Because this is a component that is created with react-grid-layout. It works without this component.