I have this drop-down (select) component named Size
as a child component and nested useFieldArray
in the parent component I am receiving warnings every time I submit it and no values are being displayed in the console. What is happening and how can I fix this?
These are the errors:
Warning: Size:
ref
is not a prop. Trying to access it will result inundefined
being returned. If you need to access the same value within the child component, you should pass it as a different prop.Field is missing
name
attribute …
Link to codesandbox: https://codesandbox.io/s/react-hook-form-usefieldarray-nested-arrays-forked-vjwbp?file=/src/Drop_drowns/Size.js
Size.js
import { InputLabel, MenuItem, FormControl, Select } from "@mui/material";
const Size = ({ name, ref, defaultValue }) => {
return (
<FormControl fullWidth variant="filled">
<InputLabel id="Size Label">Size</InputLabel>
<Select
labelId="Size"
id="size"
name={name}
label="Product"
ref={ref}
defaultValue={defaultValue}
>
<MenuItem value="S">Small</MenuItem>
<MenuItem value="M">Medium</MenuItem>
<MenuItem value="L">Large</MenuItem>
</Select>
</FormControl>
);
};
export default Size;
Nested Field Array:
import React from "react";
import { useFieldArray } from "react-hook-form";
import Size from "./Drop_drowns/Size";
import { TextField } from "@mui/material";
export default ({ nestIndex, control, register }) => {
const { fields, remove, append } = useFieldArray({
control,
name: `test[${nestIndex}].nestedArray`
});
return (
<div>
{fields.map((item, k) => {
return (
<div key={item.id} style={{ marginLeft: 20 }}>
<label>Colors:</label>
<Size
name={`test[${nestIndex}].nestedArray[${k}].field1`}
ref={register({ required: true })}
defaultValue={item.field1}
style={{ marginRight: "25px" }}
/>
{/* <input
name={`test[${nestIndex}].nestedArray[${k}].field1`}
ref={register({ required: true })}
defaultValue={item.field1}
style={{ marginRight: "25px" }}
/> */}
<TextField
name={`test[${nestIndex}].nestedArray[${k}].field2`}
ref={register()}
defaultValue={item.field2}
/>
<TextField
name={`test[${nestIndex}].nestedArray[${k}].field3`}
ref={register()}
defaultValue={item.field3}
/>
<button type="button" onClick={() => remove(k)}>
Delete Colors
</button>
</div>
);
})}
<button
type="button"
onClick={() =>
append({
field1: "field1",
field2: "field2"
})
}
>
Add Colors
</button>
<hr />
</div>
);
};
fieldArray:
import React from "react";
import { useFieldArray } from "react-hook-form";
import NestedArray from "./nestedFieldArray";
import { TextField } from "@mui/material";
let renderCount = 0;
export default function Fields({ control, register, setValue, getValues }) {
const { fields, append, remove, prepends } = useFieldArray({
control,
name: "test"
});
renderCount ;
return (
<>
<ul>
{fields.map((item, index) => {
return (
<li key={item.id}>
<TextField
name={`test[${index}].name`}
ref={register()}
defaultValue={item.name}
/>
<button type="button" onClick={() => remove(index)}>
Delete
</button>
<NestedArray nestIndex={index} {...{ control, register }} />
</li>
);
})}
</ul>
<section>
<button
type="button"
onClick={() => {
append({ name: "append" });
}}
>
Add product
</button>
{/* <button
type="button"
onClick={() => {
setValue("test", [
...getValues().test,
{
name: "append",
nestedArray: [{ field1: "append", field2: "append" }]
}
]);
}}
>
update product
</button> */}
</section>
<span className="counter">Render Count: {renderCount}</span>
</>
);
}
index.js
import React from "react";
import { useForm } from "react-hook-form";
import FieldArray from "./fieldArray";
import ReactDOM from "react-dom";
import "./styles.css";
const defaultValues = {
test: [
{
product: "",
nestedArray: [{ field1: "", field2: "", field3: "" }]
},
{
product: "",
nestedArray: [{ field1: "", field2: "", field3: "" }]
}
]
};
function App() {
const {
control,
register,
handleSubmit,
getValues,
errors,
reset,
setValue
} = useForm({
defaultValues
});
const onSubmit = (data) => console.log("data", data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<h1>Array of Array Fields</h1>
<p>
The following example demonstrate the ability of building nested array
fields.
</p>
<FieldArray
{...{ control, register, defaultValues, getValues, setValue, errors }}
/>
<button type="button" onClick={() => reset(defaultValues)}>
Reset
</button>
<input type="submit" />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
CodePudding user response:
You are attempting to pass a prop called ref
to a functional component. You can't pass refs to functional components. Also, what you're trying to pass isn't a ref. See https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element for an example of what I'm talking about. If you rename the prop ref
to reference
, referral
, referenceMaterial
, etc, you will get rid of the issue. The following error in your console on the sandbox will let you know this as well.
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Just change your props to a different, more descriptive name and you'll be in business again.