正在渲染对象数组的数组,不断收到“警告:列表中的每个孩子都应该有一个唯一的“关键”道具。”

Posted

技术标签:

【中文标题】正在渲染对象数组的数组,不断收到“警告:列表中的每个孩子都应该有一个唯一的“关键”道具。”【英文标题】:Was rendering arrays of arrays of objects, keep getting "Warning: Each child in a list should have a unique "key" prop." 【发布时间】:2020-01-10 07:27:02 【问题描述】:

我有一个包含数组数组的对象。我能够让它按照我想要的方式渲染。但是,React 键给我带来了麻烦;抛出这个“警告:列表中的每个孩子都应该有一个唯一的“关键”道具。”

我尝试在原始数组对象中为每个数组中的每个元素提供一个唯一的“id”属性,但没有帮助。

我也浏览了这些,但我认为我有所有的建议: Each child in an array or iterator should have a unique "key" prop in reactjs Warning: Each child in a list should have a unique "key" prop Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`

我的对象

const courses = 
[
    
      name: 'Half Stack application development',
      id: 'Half Stack application development',
      parts: [
        
          name: 'Fundamentals of React',
          exercises: 10,
          id: 'Fundamentals of React'
        ,
        
          name: 'Using props to pass data',
          exercises: 7,
          id: 'Using props to pass data'
        ,
        
          name: 'State of a component',
          exercises: 14,
          id: 'State of a component'
        ,
        
          name: 'Redux',
          exercises: 11,
          id: 'Redux'
        
      ]
    , 
    
      name: 'Node.js',
      id: 'Node.js',
      parts: [
        
          name: 'Routing',
          exercises: 3,
          id: 'Routing'
        ,
        
          name: 'Middlewares',
          exercises: 7,
          id: 'Middlewares'
        
        ]
    
]


ReactDOM.render(<App course=courses/>, document.getElementById('root'));

这是回调顺序:

应用程序 -> 课程 -> 课程 -> 标题,内容 -> 部分

const App = (course) => 
  return (
    <>
      <Courses course=course />
    </>
  )


const Courses = (course) => 
    console.log("Starting.....")
    const courseList = course.map(nameConent => nameConent)
    // console.log(courseList)
    // const idList = courseList.map(eachCourse =>eachCourse.id)
    const mapEverything = () => courseList.map(a => <Course name=a.name partsList=a.parts id=a.id/>)
    // const mapEverything = () => courseList.map(a => console.log(a.id))
    // console.log("CourseID",idList)
    return (
        <>  
            mapEverything()
        </>

    )


const Course = (name,partsList,id) => 
    // console.log(name)
    console.log("CourseID", id)

    return (
        <>
            <div key=id>
                <Header header=name id=id/>
                <Content contents=partsList id=id+"======"/>
            </div>
        </>
    )


const Content = (contents,id) => 
    console.log("contentsID",id)
    const partList = () => contents.map(part =>
        <Part
            name=part.name
            id=part.id 
            exercises=part.exercises
        />
    )

    const getSumofArray = (accumulator, currentValue) => accumulator + currentValue

    const exeList = contents.map(content => content.exercises).reduce(getSumofArray)
    // console.log(exeList)
    return (
        <>
            <ul key=id>
                partList()
            </ul>
            <b>total exercises: exeList</b>
        </>
    )


const Header = (header, id) => 
    console.log("HeaderID", id)
    return (
        <>
            <h1 key=id>
                header
            </h1>
        </>
    )


const Part = (name, id, exercises) => 
    console.log("PartID", id)
    return (
        <>
            <li  key=id>
                name: exercises
            </li>
        </>
    )



课程和内容组件有问题。

警告截图:https://drive.google.com/open?id=1kcLlF0d90BG6LXPojDtfSlBFGafC9HC_

【问题讨论】:

【参考方案1】:

这是关键道具的主题。每当我们在 Reactjs 中渲染一个数组或列表时,它都希望有一个可用的键属性。

这个关键属性的存在是出于性能考虑,它使 Reactjs 更容易呈现项目列表。

您所要做的就是为数组中的任何其他元素提供另一个道具。您在课程列表中拥有的最独特的标识符似乎是名称。所以你可能想把你的代码简化成这样的东西来让自己继续前进:

const CourseList = () => 
  const RenderedCourses = courses.map(function(course) 
    return <CourseDetail key=course.name course=course />;
  );
  return <ul>RenderedCourses</ul>;
;

然后,一旦你开始工作,你就可以用箭头函数和所有的方式使代码简洁:

const CourseList = () => 
  const RenderedCourses = courses.map(course => (
    <CourseDetail key=course.name course=course />
  ));
  return <ul>RenderedCourses</ul>;
;

【讨论】:

【参考方案2】:

我认为这里有问题:

const mapEverything = () => courseList.map(a => <Course name=a.name partsList=a.parts id=a.id/>)

您应该尝试在此处添加密钥:

const mapEverything = () => courseList.map(a => <Course name=a.name partsList=a.parts id=a.id key=a.id/>)

这里也是:

const partList = () => contents.map(part =>
        <Part
            name=part.name
            id=part.id 
            exercises=part.exercises
            key=part.id
        />)

Here 很好地解释了为什么需要这样做。

【讨论】:

你是对的,但请解释一下为什么我们需要key Keys 帮助 React 知道哪些元素是相同的或已更改以重用(或创建新)元素。您可以在文档中阅读更多内容或查看更多示例:reactjs.org/docs/lists-and-keys.html 等等,所以关键不是引用渲染的 HTML,而是 React 的内部?我多次阅读了 reactjs 文档,并认为它需要成为渲染 DOM 的一部分,尽管它是隐藏的。另外,如果您查看我的屏幕截图,所有 Key 的值都能够传递给每个回调组件,为什么我需要显式传递另一个“Key”组件? @TimothyCumberland 是的,你说得对,React 的内部功能需要它。

以上是关于正在渲染对象数组的数组,不断收到“警告:列表中的每个孩子都应该有一个唯一的“关键”道具。”的主要内容,如果未能解决你的问题,请参考以下文章

对象作为 React 子级无效如果您要渲染子级集合,请改用数组

无法使用数组成员变量分配数组

如何通过 React 中的嵌套对象数组进行映射

AJAX 将对象数组发布到端点

将文本字段绑定到数组中的对象时出错

保存不断附加的自定义对象数组