警告:数组或迭代器中的每个 child 都应该有一个唯一的 "key" 属性
Warning: Each child in an array or iterator should have a unique "key" prop
你好。
我想迭代一堆 JSON objects 并将它们变成 React Elements。 objects 看起来像这样
"fields":
[
{
key: "testname",
"name": "testname",
"altName": "",
"visible": true,
"groupVisibility": "public",
"type": "text",
"component": "input",
"label": "Test Smart Input",
"placeholder": "Some default Value",
"required": "required",
"validated": false,
"data": []
},
{
key: "password",
"name": "password",
"altName": "",
"visible": true,
"groupVisibility": "public",
"type": "password",
"component": "input",
"label": "Test Smart Input",
"placeholder": "Password",
"required": "required",
"validated": false,
"data": []
}
]
并且遍历它们的代码非常简单。这样:
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
console.log('doin fields');
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
fieldIn,
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
我得到了错误
警告:数组或迭代器中的每个 child 都应该有一个唯一的 "key" 属性。
有什么提示吗?
干杯
我更改了代码来执行此操作。
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
console.log('doin fields');
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].name, fieldIn},
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
我得到了同样的错误。我不明白为什么!
固定的!谢谢您的帮助。
这是代码。
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].key, fieldIn},
null); // lowest level, no children, data is in props
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
//----------------------
pages(pagesIn, format) {
// I tried to do this in JSX, but no syntax I wrestled with would
// allow me to access the childred when building this with the
// BABEL transpiler. Same goes for the METHOD just above, items().
//
// This method returns an array of pages this are React elements
// this are treated as children by the smartForm.
const pagesOut = []; // array of pages to build and return
let Section = {}; // Component to fire in the build
switch(format) {
case 'accordion': {
Section = AccordionSection;
break;
}
case 'workflow': {
Section = null; // I haven't written this yet
break;
}
case 'simple': {
Section = null; // I haven't written this yet
break;
}
}
for (var pageIn in pagesIn) { // pages, any format, any number 1..N
let children = this.formFields(pagesIn[pageIn].fields); // 1..N fields, we don't know beforehand
let page = React.createElement( Section,
pagesIn[pageIn].props,
children);
pagesOut.push(page);
}
return(pagesOut); // this ARRAY is the children of each FORM
}
//--------
render() {
let formIn = this.props.form; // JSON description of FORM
let formOut = null; // contructed REACT/Javascript form
switch (formIn.format) { // what type of operation is this
case 'accordion': { // Accordion in a FORM, OK
let children = this.pages(formIn.pages,
formIn.format); // build the children
formOut = React.createElement(Accordion, // construct the parent with ALL nested CHILDREN after
{key: formIn.formName}, // just a unique key
children); // N ACCORDION pages, N2 input fields
break;
}
case 'workflow': {
let children = this.pages(formIn.pages, // build the children
formIn.format); // build the children
formOut = React.createElement(Workflow, // and create the complex sheet element
{ key: formIn.formName},
children); // N SLIDING pages, N2 input fields
break;
}
case 'simple': {
let children = this.pages(formIn.pages, // build the children
formIn.format); // build the children
formOut = React.createElement(Simple,
{ key: formIn.formName},
children); // One page, N input fields
break;
}
}
return(
<div>
<h2>SmartForm Parser</h2>
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
{formOut}
</div>
);
}
}
//-------------------------------------------------------------------------
export default SmartForm;
//----------------- EOF -------------------------------------------------
您需要为您的 React 元素添加一个唯一的 key 道具。
根据React docs:
Keys
help React identify which items have changed, are added, or are
removed. Keys should be given to the elements inside the array to give
the elements a stable identity.
The best way to pick a key is to use a string that uniquely identifies
a list item among its siblings. Most often you would use IDs from your
data as keys
When you don’t have stable IDs for rendered items, you may use the
item index as a key as a last resort
你可以这样做
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].key, fieldIn},
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
为什么需要密钥?
默认情况下,当对 DOM 节点的子节点进行递归时,React 只会同时迭代两个子节点列表,并在存在差异时生成一个突变。
例如,在子节点末尾添加一个元素时,在这两个树之间进行转换效果很好:
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
React会匹配两棵<li>first</li>
树,匹配两棵<li>second</li>
树,然后插入<li>third</li>
树。
如果你天真地实现它,在开头插入一个元素性能会更差。例如,在这两棵树之间进行转换效果不佳。
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>third</li>
<li>first</li>
<li>second</li>
</ul>
这就是钥匙派上用场的地方。
你好。 我想迭代一堆 JSON objects 并将它们变成 React Elements。 objects 看起来像这样
"fields":
[
{
key: "testname",
"name": "testname",
"altName": "",
"visible": true,
"groupVisibility": "public",
"type": "text",
"component": "input",
"label": "Test Smart Input",
"placeholder": "Some default Value",
"required": "required",
"validated": false,
"data": []
},
{
key: "password",
"name": "password",
"altName": "",
"visible": true,
"groupVisibility": "public",
"type": "password",
"component": "input",
"label": "Test Smart Input",
"placeholder": "Password",
"required": "required",
"validated": false,
"data": []
}
]
并且遍历它们的代码非常简单。这样:
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
console.log('doin fields');
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
fieldIn,
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
我得到了错误 警告:数组或迭代器中的每个 child 都应该有一个唯一的 "key" 属性。 有什么提示吗? 干杯
我更改了代码来执行此操作。
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
console.log('doin fields');
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].name, fieldIn},
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
我得到了同样的错误。我不明白为什么! 固定的!谢谢您的帮助。
这是代码。
//--------------------
formFields(fieldsIn) {
const fieldsOut = []; // ARRAY of FORM ELEMENTS to return
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].key, fieldIn},
null); // lowest level, no children, data is in props
fieldsOut.push(field);
}
return(fieldsOut); // this ARRAY is the children of each PAGE
}
//----------------------
pages(pagesIn, format) {
// I tried to do this in JSX, but no syntax I wrestled with would
// allow me to access the childred when building this with the
// BABEL transpiler. Same goes for the METHOD just above, items().
//
// This method returns an array of pages this are React elements
// this are treated as children by the smartForm.
const pagesOut = []; // array of pages to build and return
let Section = {}; // Component to fire in the build
switch(format) {
case 'accordion': {
Section = AccordionSection;
break;
}
case 'workflow': {
Section = null; // I haven't written this yet
break;
}
case 'simple': {
Section = null; // I haven't written this yet
break;
}
}
for (var pageIn in pagesIn) { // pages, any format, any number 1..N
let children = this.formFields(pagesIn[pageIn].fields); // 1..N fields, we don't know beforehand
let page = React.createElement( Section,
pagesIn[pageIn].props,
children);
pagesOut.push(page);
}
return(pagesOut); // this ARRAY is the children of each FORM
}
//--------
render() {
let formIn = this.props.form; // JSON description of FORM
let formOut = null; // contructed REACT/Javascript form
switch (formIn.format) { // what type of operation is this
case 'accordion': { // Accordion in a FORM, OK
let children = this.pages(formIn.pages,
formIn.format); // build the children
formOut = React.createElement(Accordion, // construct the parent with ALL nested CHILDREN after
{key: formIn.formName}, // just a unique key
children); // N ACCORDION pages, N2 input fields
break;
}
case 'workflow': {
let children = this.pages(formIn.pages, // build the children
formIn.format); // build the children
formOut = React.createElement(Workflow, // and create the complex sheet element
{ key: formIn.formName},
children); // N SLIDING pages, N2 input fields
break;
}
case 'simple': {
let children = this.pages(formIn.pages, // build the children
formIn.format); // build the children
formOut = React.createElement(Simple,
{ key: formIn.formName},
children); // One page, N input fields
break;
}
}
return(
<div>
<h2>SmartForm Parser</h2>
<p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</p>
{formOut}
</div>
);
}
}
//-------------------------------------------------------------------------
export default SmartForm;
//----------------- EOF -------------------------------------------------
您需要为您的 React 元素添加一个唯一的 key 道具。
根据React docs:
Keys
help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys
When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort
你可以这样做
for (var fieldIn in fieldsIn) { // array of FORM ELEMENT descriptions in JSON
console.log(fieldIn);
let field = React.createElement(SmartRender, // go build the React Element
{key: fieldsIn[fieldIn].key, fieldIn},
null); // lowest level, no children, data is in props
console.log('doin fields inside');
fieldsOut.push(field);
}
为什么需要密钥?
默认情况下,当对 DOM 节点的子节点进行递归时,React 只会同时迭代两个子节点列表,并在存在差异时生成一个突变。
例如,在子节点末尾添加一个元素时,在这两个树之间进行转换效果很好:
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
React会匹配两棵<li>first</li>
树,匹配两棵<li>second</li>
树,然后插入<li>third</li>
树。
如果你天真地实现它,在开头插入一个元素性能会更差。例如,在这两棵树之间进行转换效果不佳。
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>third</li>
<li>first</li>
<li>second</li>
</ul>
这就是钥匙派上用场的地方。