我试图在我的反应应用程序中创建一个表单。我创建了一个input.js组件,它被导入到我的contact.js组件中,然后映射。我得到一个“警告:数组或迭代器中的每个孩子都应该有一个唯一的“键”道具。检查控制台内部的输入
的渲染方法,但是我不明白为什么,因为每个输入组件都已经设置了唯一的键。当我在铬检测仪的反应选项卡中检查它们时,它们都有一个唯一的密钥集。
这是我的contact.js组件:
import React, { Component } from 'react';
import Input from './Input/input';
import Button from './Button/Button';
import Spinner from '../UI/Spinner/Spinner';
import {checkValidity} from '../../shared/utility';
import axios from '../../axios-contact';
class ContactForm extends Component {
state = {
contactForm: {
name: {
elementType: 'input',
elementConfig: {
inputprops: {
type: 'text',
id: 'name',
name: 'name',
required: 'required'
} ,
label: 'Name',
htmlFor: 'name',
invalid: 'Please enter your firstname',
value: '',
},
validation: {
required: true,
minLength: 2,
maxLength: 30
},
valid: false,
touched: false
},
company: {
elementType: 'input',
elementConfig: {
inputprops: {
type: 'text',
id: 'company',
name: 'company',
required: 'required'
},
label: 'Company',
htmlFor: 'company',
invalid: 'Please enter your company name',
value: '',
},
validation: {
required: true,
minLength: 2,
maxLength: 30
},
valid: false,
touched: false
},
location: {
elementType: 'input',
elementConfig: {
inputprops: {
type: 'text',
id: 'location',
name: 'location',
required: 'required'
},
label: 'Company location (city / country)',
htmlFor: 'location',
invalid: 'Please enter your location',
value: '',
},
validation: {
required: true,
minLength: 2,
maxLength: 30
},
valid: false,
touched: false
},
email: {
elementType: 'email',
elementConfig: {
inputprops: {
type: 'email',
id: 'email',
name: 'email',
required: 'required'
},
label: 'Email',
htmlFor: 'email',
invalid: 'Please enter a propper email address',
value: '',
},
validation: {
required: true,
isEmail: true,
minLength: 7,
maxLength: 40
},
valid: false,
touched: false
},
phone: {
elementType: 'input',
elementConfig: {
inputprops: {
type: 'tel',
id: 'phone',
name: 'phone',
required: false
},
label: 'Phone',
htmlFor: 'phone',
invalid: 'Please enter a propper phone number',
value: '',
},
validation: {
required: false,
minLength: 6,
maxLength: 30
},
valid: true,
touched: false
},
message: {
elementType: 'textarea',
elementConfig: {
inputprops: {
type: 'textarea',
id: 'message',
name: 'message',
required: 'required',
rows: 4
},
label: 'Message',
htmlFor: 'message',
invalid: 'Please enter a message',
value: '',
},
validation: {
required: true,
minLength: 2,
maxLength: 500
},
valid: false,
touched: false
},
compliance: {
elementType: 'checkbox',
containerClass: 'custom-control custom-checkbox',
inputClass: 'custom-control-input',
elementConfig: {
inputprops: {
type: 'checkbox',
id: 'gdpr',
name: 'gdpr',
required: 'required'
},
label: 'I consent to having this website store my submitted information so they can respond to my inquiry.',
htmlFor: 'gdpr',
invalid: 'Please give your consent before proceeding',
value: '',
},
validation: {
required: true,
isCheckbox: true,
isToggled: false
},
valid: false,
touched: false
}
},
formIsValid: false,
loading: false,
sent: false
}
contactHandler = ( event ) => {
event.preventDefault();
this.setState( { loading: true } );
const formData = {}
for (let formElementIdentifier in this.state.contactForm) {
formData[formElementIdentifier] = this.state.contactForm[formElementIdentifier].elementConfig.value;
}
axios.post('/contacts.json', formData)
.then(response => {
this.setState({ loading: false, sent: true });
console.log(formData);
})
.catch(error => {
this.setState({ loading: false, sent: true });
console.log(formData);
});
}
inputChangedHandler = (event, inputIdentifier) => {
const updatedContactForm = {
...this.state.contactForm
};
const updatedFormElement = {
...updatedContactForm[inputIdentifier]
};
updatedFormElement.elementConfig.value = event.target.value;
updatedFormElement.valid = checkValidity(updatedFormElement.elementConfig.value, updatedFormElement.validation);
updatedFormElement.touched = true;
updatedFormElement.validation.isToggled = !updatedFormElement.validation.isToggled;
updatedContactForm[inputIdentifier] = updatedFormElement;
let formIsValid = true;
for ( let inputIdentifier in updatedContactForm) {
formIsValid = updatedContactForm[inputIdentifier].valid && formIsValid;
}
this.setState({contactForm: updatedContactForm, formIsValid: formIsValid});
}
render () {
const formElementsArray = [];
for (let key in this.state.contactForm) {
formElementsArray.push({
id: key,
config: this.state.contactForm[key]
});
}
let form = (
<form onSubmit={this.contactHandler} name="contact">
{formElementsArray.map(formElement =>(
<Input
key={formElement.id}
elementType={formElement.config.elementType}
containerClass={formElement.config.containerClass}
inputClass={formElement.config.inputClass}
elementConfig={formElement.config.elementConfig}
value={formElement.config.value}
invalid={!formElement.config.valid}
shoudValidate={formElement.config.validation}
touched={formElement.config.touched}
checked={formElement.config.validation.isToggled}
changed={(event) => this.inputChangedHandler(event, formElement.id)}
exited={(event) => this.inputChangedHandler(event, formElement.id)} />
))}
<Button disabled={!this.state.formIsValid} />
</form>
);
if (this.state.loading) {
form = <Spinner />
}
if (this.state.sent) {
form = <p id="contact-message" className="contact-message">Thank you for your message.<br /> We will respond as soon as possible.</p>
}
return (
<div className="contact">
<section id="contact-form" className="contact-form">
<h1>Contact</h1>
{form}
</section>
</div>
)
}
};
export default ContactForm;
这是我的意见。js组件:
import React from 'react';
import { NavLink } from 'react-router-dom';
const input = ( props ) => {
let label = <label htmlFor={props.elementConfig.htmlFor}>{props.elementConfig.label}</label>;
let inputElement = null;
let errorlabel = null;
let inputClass = ['input'];
const errorid = [props.elementConfig.id];
if(props.invalid && props.shoudValidate && props.touched) {
inputClass.push('error');
}
switch (props.elementType) {
case ('input'):
inputElement = <input
className ={inputClass.join(' ')}
{...props.elementConfig.inputprops}
value={props.elementConfig.value}
onChange={props.changed}
onBlur={props.exited} />;
break;
case ('email'):
inputElement = <input
className ={inputClass.join(' ')}
{...props.elementConfig.inputprops}
value={props.elementConfig.value}
onChange={props.changed}
onBlur={props.exited} />;
break;
case ( 'textarea' ):
inputElement = <textarea
className ={inputClass.join(' ')}
{...props.elementConfig.inputprops}
value={props.elementConfig.value}
onChange={props.changed}
onBlur={props.exited} />;
break;
case ( 'checkbox' ):
inputElement = <input
className ={[props.inputClass, inputClass.join(' ')].join(' ')}
{...props.elementConfig.inputprops}
value={!props.checked}
onChange={props.changed} />;
label = <label htmlFor={props.elementConfig.htmlFor} className="custom-control-label">This form collects your name, e-mail, phone number, company name, and location so that we may correspond with you. Read our <NavLink to="/privacy" exact>privacy policy</NavLink> for more information. By submitting the form, you consent to have StackApp collect the listed information.</label>;
break;
default:
inputElement = <input
className ={inputClass.join(' ')}
{...props.elementConfig.inputprops}
value={props.elementConfig.value}
onChange={props.changed}
onBlur={props.exited} />;
}
if(props.invalid && props.touched) {
errorlabel = <label id={errorid.join('-error')} className="error" htmlFor={props.elementConfig.htmlFor}>{props.elementConfig.invalid}</label>
};
let output = null;
if(props.elementType === 'checkbox') {
output = [inputElement, label, errorlabel];
} else {
output = [label, inputElement, errorlabel];
}
return (
<div role="group" className={props.containerClass}>
{output}
</div>
)
};
export default input;
我错过了什么?
即使formElementsArray。map
似乎是最有可能的候选,但在本例中,它不是警告的来源。正如您在评论中提到的,每个键的构造都是唯一的。错误来自输入。js,在这里分配output=[inputElement,label,errorlabel]
然后直接呈现{output}
。React看到这是一个数组,但不知道它的大小是固定的,并希望数组中的每个元素都有一个唯一的键
属性。如果在输入元素
、标签
和错误标签
上放置键
道具,则警告应消失。
问题内容: 这个问题需要一些假设的背景。让我们考虑一个有列的表,,,,使用MySQL作为RDBMS。由于如果给定的某个人的名字和出生日期与另一个人相同,那么根据定义,他们就是同一个人(除非有两个巧合,即我们两个人分别于1809年2月12日出生,他们叫亚伯拉罕·林肯),所以我们将上的唯一键,这意味着“不要将同一个人存储两次”。现在考虑以下数据: 如果现在尝试运行以下语句,则该语句应该并且将失败: 如
我正在尝试我们非主键作为外键在我的应用程序。场景如下:我有EMPLOYEE和EMPLOYEE_PROPERTIES表。Employee和Employee属性之间存在一对多的关系。下面是我的架构: 下面是我的hibernate映射XML:------------------------------- -------------员工属性------------------- 是否可以引用非主键作为外键
我使用uuidv4输入字段唯一的关键字,我甚至通过传递数组索引作为唯一的道具检查,但我得到相同的警告反应。StackOverflow上的一个类似问题建议在最外层的JSX标签上使用密钥,所以我将密钥放在
所以我想渲染数组,但它一直在说,警告:列表中的每个孩子都应该有一个唯一的“键”道具,即使它有唯一的键,我的数组包含三个元素,它甚至没有正确渲染第三个数组,按钮没有甚至因为某种原因第三李的工作。 更新:我从firebase获得的数据如下所示: 此代码将选择每个数据的标题 当我将鼠标悬停在“fikka-fikka”上时,“fikka-fikka”的按钮甚至不起作用。在ed sheeran和一个方向上,
得到一个警告:列表中的每个孩子都应该有一个唯一的“键”道具。我想不出我需要用哪把钥匙。 我红了反应指南,但它不能帮助我理解如何在我的情况下使用它
问题内容: G’Day。我想遍历一堆JSON对象,然后将它们变成React Elements。对象看起来像这样 遍历它们的代码非常简单。这样: 而且我收到错误警告:数组或迭代器中的每个子代都应具有唯一的“键”属性。有什么提示吗?干杯 我更改了代码以执行此操作。 而且我得到同样的错误。我不明白为什么!固定!谢谢您的帮助。 这是代码。 问题答案: 您需要向React元素添加一个唯一的key prop。