我遇到了一个问题,React 抱怨一个关键 prop 被传播到 JSX 元素中,即使我没有明确地将它作为 props 的一部分传递。
以下是相关代码片段:
<Input
className="mb-[20px]"
label="First Name"
errorMessage={fields.firstName.errors?.at(0)}
{...getInputProps(fields.firstName, { type: "text" })}
/>
错误信息:
A props object containing a "key" prop is being spread into JSX:
let props = {key: someKey, className: ..., label: ..., errorMessage: ..., required: ..., id: ..., name: ..., form: ..., type: ..., minLength: ...};
<Input {...props} />
React keys must be passed directly to JSX without using spread:
let props = {className: ..., label: ..., errorMessage: ..., required: ..., id: ..., name: ..., form: ..., type: ..., minLength: ...};
<Input key={someKey} {...props} />
符合文档:https://conform.guide/api/react/getInputProps
以下是完整表格:
"use client";
import { useActionState } from "react";
import { getFormProps, getInputProps, useForm } from "@conform-to/react";
import { getZodConstraint, parseWithZod } from "@conform-to/zod";
import { signUpWithDetails } from "@/features/authentication/actions";
import { SignUpSchema } from "@/features/authentication/schemas/sign-up";
import { Input } from "@/common/components/Form/Input/Input";
import { Button } from "@/common/components/Form/Button/Button";
import { DatePicker } from "@/common/components/Form/DatePicker/DatePicker";
interface DetailsFormProps {
email: string;
}
export const DetailsForm = ({ email }: DetailsFormProps) => {
const [lastResult, action, pending] = useActionState(
signUpWithDetails,
undefined,
);
const [form, fields] = useForm({
lastResult,
constraint: getZodConstraint(SignUpSchema),
onValidate({ formData }) {
return parseWithZod(formData, { schema: SignUpSchema });
},
shouldValidate: "onSubmit",
shouldRevalidate: "onInput",
});
return (
<form className="w-full" action={action} {...getFormProps(form)}>
<input type="hidden" name="email" value={email} />
<Input
className="mb-[20px]"
label="First Name"
errorMessage={fields.firstName.errors?.at(0)}
{...getInputProps(fields.firstName, { type: "text" })}
/>
<Input
className="mb-[20px]"
label="Last Name"
errorMessage={fields.lastName.errors?.at(0)}
{...getInputProps(fields.lastName, { type: "text" })}
/>
<DatePicker
className="mb-[20px]"
label="Date of Birth"
max={new Date().toJSON().slice(0, 10)}
errorMessage={fields.dateOfBirth?.errors?.at(0)}
{...getInputProps(fields.dateOfBirth, { type: "date" })}
/>
<Input
className="mb-10"
label="Password"
errorMessage={fields.password.errors?.at(0)}
{...getInputProps(fields.password, { type: "password" })}
/>
<Button
className="w-full mb-6"
label="Continue"
variant="primary"
type="submit"
isLoading={pending}
/>
</form>
);
};
在 React 中使用 key 属性时,将其放置在展开运算符之前非常重要。
key 属性帮助 React 更有效地识别和管理列表中的元素,特别是当列表发生变化时(例如添加、删除或重新排序项目)。
如果将键放在扩展运算符之后,则键的值可能会被您正在扩展的对象中的属性覆盖。这可能会导致意外行为,因为 React 可能无法正确分配密钥
不正确
<Input
className="mb-[20px]"
label="Last Name"
errorMessage={fields.lastName.errors?.at(0)}
{...getInputProps(fields.lastName, { type: "text" })}
/>
正确
<Input key={}
className="mb-[20px]"
label="Last Name"
errorMessage={fields.lastName.errors?.at(0)}
{...getInputProps(fields.lastName, { type: "text" })}
key={fields.title.key}
/>
参考:https://github.com/vercel/next.js/issues/55642#issuecomment-1728746491