Formik渲染字段列表时React触发唯一key prop警告求助
解决React列表key警告问题
问题根源
你的代码里有两处引发警告的问题:
- 下拉选项
<option>循环渲染时没加唯一key - 外层div用
index当key(虽能临时消警告,但不是最优方案)
修复步骤
1. 给下拉选项补全key
在field.options.map的<option>上添加key={option.value},因为选项的value本身是唯一标识:
{field.options.map((option) => ( <option key={option.value} value={option.value}> {option.label} </option> ))}
2. 替换index为更稳定的key
把外层div的key={index}换成key={field.name}——表单字段的name属性天生唯一,比index更稳定(数组元素顺序变化时,React不会误判元素身份):
{fields.map((field) => ( <div key={field.name}> {/* 原有表单元素代码 */} </div> ))}
3. (可选)移除多余的FieldArray组件
你当前没用到Formik FieldArray的数组操作能力,只是用它包裹了自己的fields循环,直接移除FieldArray、直接渲染循环即可,代码更简洁:
// 删掉<FieldArray>标签,直接写循环 {fields.map((field) => ( <div key={field.name}> {/* 原有内容 */} </div> ))}
修复后的关键代码片段
<Formik initialValues={initialValues} onSubmit={onSubmit} validate={validate} > {({ values, handleSubmit, handleChange, errors }: formikProps) => ( <form onSubmit={handleSubmit} className={`space-y-4 sm:space-y-0 ${ formType === "login" ? "" : "sm:grid sm:grid-cols-2 sm:grid-rows-[auto_auto_auto_auto_auto_40px]" } flex flex-col gap-4`} > {fields.map((field) => ( <div key={field.name}> <label htmlFor={field.name} className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > {field.label} </label> {field.options && ( <select name={field.name} value={values[field.name]} onChange={handleChange} className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" data-testid={`${field.name}-input`} > {field.options.map((option) => ( <option key={option.value} value={option.value}> {option.label} </option> ))} </select> )} {!field.options && ( <input type={field.type} name={field.name} value={values[field.name]} onChange={handleChange} placeholder={field.placeholder} className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" data-testid={`${field.name}-input`} /> )} {errors[field.name] && ( <div className="text-red-500 text-xs italic"> {errors[field.name]} </div> )} </div> ))} <Button type="submit" className="w-full col-span-2"> {submitLabel} </Button> <span className="text-xs text-gray-500 dark:text-gray-400"> {message} </span> </form> )} </Formik>
内容的提问来源于stack exchange,提问作者dcselek
相关产品推荐
相关产品推荐

