I have a main component here:
// import { useState } from "react";
import {
useForm,
Controller,
FormProvider,
SubmitHandler,
} from "react-hook-form";
// import "./App.css";
import { Box, Button, TextField } from "@mui/material";
import { useState } from "react";
import NestedForm from "./NestedForm";
type Inputs = {
outerInput: string;
};
type InnerInput = {
innerString1: string;
innerString2: string;
};
function App() {
const methods = useForm<Inputs>({
shouldUnregister: true,
});
const [innerInput, setInnerInput] = useState<InnerInput[]>([
{ innerString1: "test1", innerString2: "test2" },
{ innerString1: "test3", innerString2: "test4" },
{ innerString1: "test5", innerString2: "test6" },
{ innerString1: "test7", innerString2: "test8" },
{ innerString1: "test9", innerString2: "test10" },
]);
const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);
function removeItem(idx: number) {
setInnerInput((prevInnerInput) =>
prevInnerInput.filter((_, index) => index !== idx)
);
}
return (
<>
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(onSubmit)}>
<div className="relative mb-5 flex">
<div className="w-7/12">
<Controller
control={methods.control}
name="outerInput"
defaultValue=""
render={({ field, fieldState }) => (
<TextField
label="Outer Input"
error={!!fieldState.error}
helperText={fieldState.error?.message}
{...field}
fullWidth
variant="standard"
type="text"
/>
)}
/>
</div>
{innerInput.map((item, idx) => (
<NestedForm
key={`inner-${idx}`}
idx={idx}
data={item}
handleRemove={() => removeItem(idx)}
/>
))}
</div>
<Box width={"20%"} display="flex" justifyContent={"center"}>
<Button type="submit">Save</Button>
</Box>
</form>
</FormProvider>
</>
);
}
export default App;
And a Nested form with tow textfields:
import { Box, Button, TextField } from "@mui/material";
import { useFormContext } from "react-hook-form";
type InnerInput = {
innerString1: string;
innerString2: string;
};
function NestedForm({
idx,
data,
handleRemove,
}: {
idx: number;
data: InnerInput;
handleRemove: () => void;
}) {
const { register } = useFormContext();
return (
<div>
<TextField
{...register(`inner[${idx}.innerString1`)}
label="Inner Input 1"
defaultValue={data.innerString1}
fullWidth
variant="standard"
type="text"
/>
<TextField
{...register(`inner[${idx}.innerString2`)}
defaultValue={data.innerString2}
label="Inner Input 2"
fullWidth
variant="standard"
type="text"
/>
<Box width={"20%"} display="flex" justifyContent={"center"}>
<Button onClick={handleRemove}>Remove</Button>
</Box>
</div>
);
}
export default NestedForm;
I am getting a strange behavior.
When I click on Remove
on the first item, this will remove the last each time I click on the Remove, and finally when none left this will remove the first item.
But still when I click on Submit, I can still see all the items of the innerInput
New contributor
Bálint Ipkovich is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.