警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”prop

IT技术 reactjs ecmascript-6 javascript-objects ecmascript-5
2021-04-17 15:01:34

G'Day。我想遍历一堆 JSON 对象并将它们转换为 React Elements。对象看起来像这样

                                "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
}

我收到错误警告:数组或迭代器中的每个子项都应该有一个唯一的“键”props。任何提示?干杯

我改变了代码来做到这一点。

//--------------------
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 -------------------------------------------------
1个回答

你需要为你的 React 元素添加一个唯一的 key prop。

根据React 文档

Keys帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以赋予元素稳定的身份。

选择键的最佳方法是使用一个字符串,该字符串在其兄弟项中唯一标识列表项。大多数情况下,您会使用数据中的 ID 作为键

当您没有呈现项目的稳定 ID 时,您可以将项目索引用作键作为最后的手段

你可以这样做

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>

这就是钥匙派上用场的地方。

谢了哥们。我的整个 fieldsIn 结构未定义!整理好后我会在这里发布。
2021-05-29 15:01:34
您的 json 对象中的键是否唯一,请检查是否fieldsIn[fieldIn].key为您提供了正确的键值,我假设它是您索引的内容而添加它
2021-06-05 15:01:34
我编辑了我的原始帖子以反映我的代码更改。我得到了同样的错误......我在这里遗漏了一些东西!
2021-06-09 15:01:34