使用 React-Hook-Forms 将子组件(下拉)传递给父组件:ref 不是 prop,提交时不保存任何值
Passing a child component(drop down) to the parent component with React-Hook-Forms: ref is not a prop & no values saved when submitted
我将这个名为 Size
的下拉 (select) 组件作为子组件并嵌套在父组件中 useFieldArray
我每次提交它时都会收到警告,并且控制台中未显示任何值。发生了什么事,我该如何解决?
这些是错误:
Warning: Size: ref
is not a prop. Trying to access it will result in
undefined
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 到 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;
嵌套字段数组:
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>
);
};
字段数组:
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);
您正在尝试将名为 ref
的道具传递给功能组件。您不能将 refs 传递给功能组件。另外,您要传递的不是参考。请参阅 https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element 以了解我正在谈论的示例。如果您将道具 ref
重命名为 reference
、referral
、referenceMaterial
等,您将摆脱这个问题。沙盒控制台中的以下错误也会让您知道这一点。
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
只需将您的道具更改为不同的、更具描述性的名称,您就可以再次开展业务。
编辑:
还,
编辑:
另外,我看到您正在将方法 register
传递给 refer。我不确定您是否立即需要一个作为道具传递的结果。如果是这样,你很好。如果你需要传递函数,你必须用匿名函数包装它以确保它不会立即被调用:
<Element props={() => {register({ required: true })}} />
封装函数后,不会立即调用它。
当你传递寄存器时,你传递的是函数。
当您传递 register() 时,您传递的是返回的结果,因为该函数会立即被调用。
这都是关于括号的。如果有括号,它会立即被调用。
我将这个名为 Size
的下拉 (select) 组件作为子组件并嵌套在父组件中 useFieldArray
我每次提交它时都会收到警告,并且控制台中未显示任何值。发生了什么事,我该如何解决?
这些是错误:
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 到 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;
嵌套字段数组:
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>
);
};
字段数组:
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);
您正在尝试将名为 ref
的道具传递给功能组件。您不能将 refs 传递给功能组件。另外,您要传递的不是参考。请参阅 https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element 以了解我正在谈论的示例。如果您将道具 ref
重命名为 reference
、referral
、referenceMaterial
等,您将摆脱这个问题。沙盒控制台中的以下错误也会让您知道这一点。
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
只需将您的道具更改为不同的、更具描述性的名称,您就可以再次开展业务。
编辑:
还,
编辑:
另外,我看到您正在将方法 register
传递给 refer。我不确定您是否立即需要一个作为道具传递的结果。如果是这样,你很好。如果你需要传递函数,你必须用匿名函数包装它以确保它不会立即被调用:
<Element props={() => {register({ required: true })}} />
封装函数后,不会立即调用它。 当你传递寄存器时,你传递的是函数。 当您传递 register() 时,您传递的是返回的结果,因为该函数会立即被调用。 这都是关于括号的。如果有括号,它会立即被调用。