Map 在 React 中的第一次迭代后停止迭代

Posted

技术标签:

【中文标题】Map 在 React 中的第一次迭代后停止迭代【英文标题】:Map stops iterating after first iteration in React 【发布时间】:2020-12-15 22:50:13 【问题描述】:

我的组件应该在组件挂载时检索课程数据。我遇到的问题是,无论我使用课程 ID 还是课程标题​​作为键,我都会收到以下错误:

index.js:1 警告:列表中的每个孩子都应该有一个唯一的“key”属性。

我查看了 Stack Overflow 上的 react 文档,并尝试了不同的方法来使其工作。我可以让它部分工作的唯一方法是添加一个索引作为地图的参数。当我使用这种方法时,我遇到了另一个问题,即它在第一次迭代后停止,即使有 10 个项目。我该如何解决这个问题?

这是我的代码:

CoursesPage.js

import React from 'react';
import  connect  from 'react-redux';
import * as courseActions from '../../redux/actions/courseActions';
import PropTypes from 'prop-types';
import  bindActionCreators  from 'redux';

class CoursesPage extends React.Component 

    componentDidMount() 
        this.props.actions.loadCourses().catch(error => 
            alert("Loading courses failed" + error);
        );

    


    render() 
        return (
            <>
                <h2>Courses</h2>

                

this.props.courses.map((course, index) => (

                    <div key=course[index].title>course[index].title</div>


                ))
            </>
        );
    


CoursesPage.propTypes = 
    courses: PropTypes.array.isRequired,
    actions: PropTypes.object.isRequired


function mapStateToProps(state) 
    return 
        courses: state.courses
    



function mapDispatchToProps(dispatch) 

    return 
        actions: bindActionCreators(courseActions, dispatch)
    



export default connect(mapStateToProps, mapDispatchToProps)(CoursesPage);

我的模拟数据:

const courses = [
    
        id: 1,
        title: "Securing React Apps with Auth0",
        slug: "react-auth0-authentication-security",
        authorId: 1,
        category: "javascript"
    ,
    
        id: 2,
        title: "React: The Big Picture",
        slug: "react-big-picture",
        authorId: 1,
        category: "JavaScript"
    ,
    
        id: 3,
        title: "Creating Reusable React Components",
        slug: "react-creating-reusable-components",
        authorId: 1,
        category: "JavaScript"
    ,
    
        id: 4,
        title: "Building a JavaScript Development Environment",
        slug: "javascript-development-environment",
        authorId: 1,
        category: "JavaScript"
    ,
    
        id: 5,
        title: "Building Applications with React and Redux",
        slug: "react-redux-react-router-es6",
        authorId: 1,
        category: "JavaScript"
    ,
    
        id: 6,
        title: "Building Applications in React and Flux",
        slug: "react-flux-building-applications",
        authorId: 1,
        category: "JavaScript"
    ,
    
        id: 7,
        title: "Clean Code: Writing Code for Humans",
        slug: "writing-clean-code-humans",
        authorId: 1,
        category: "Software Practices"
    ,
    
        id: 8,
        title: "Architecture Applications for the Real World",
        slug: "architecting-applications-dotnet",
        authorId: 1,
        category: "Software Architecture"
    ,
    
        id: 9,
        title: "Becoming an Outlier: Reprogramming the Developer Mind",
        slug: "career-reboot-for-developer-mind",
        authorId: 1,
        category: "Career"
    ,
    
        id: 10,
        title: "Web Component Fundamentals",
        slug: "web-components-shadow-dom",
        authorId: 1,
        category: "html5"
    
];

const authors = [
     id: 1, name: "Cory House" ,
     id: 2, name: "Scott Allen" ,
     id: 3, name: "Dan Wahlin" 
];

const newCourse = 
    id: null,
    title: "",
    authorId: null,
    category: ""
;

module.exports = 
    newCourse,
    courses,
    authors
;

编辑: 我正在使用 Redux Thunk。

这是我的 actionType.js 文件:

export const CREATE_COURSE = "CREATE_COURSE";
export const LOAD_COURSES_SUCCESS = "LOAD_COURSES_SUCCESS";

这是我的 CourseActions.js 文件:

import * as types from './actionTypes';
import * as courseApi from "../../api/courseApi";

export function createCourse(course) 
    return  type: types.CREATE_COURSE, course ;


export function loadCourseSuccess(courses) 
    return  type: types.LOAD_COURSES_SUCCESS, courses ;


export function loadCourses() 
    return function (dispatch) 
        return courseApi.getCourses().then(courses => 
            dispatch(loadCourseSuccess(courses));
        ).catch(error => 
            throw error;
        )

    

这是我的 courseReducer.js 文件:

import * as types from '../actions/actionTypes';

export default function courseReducer(state = [], action) 

    switch (action.type) 
        case types.CREATE_COURSE:
            return [...state,  ...action.course ];

        case types.LOAD_COURSES_SUCCESS:
            return [...state,  ...action.courses ];

        default:
            return state;
    


任何帮助将不胜感激。

谢谢。

附注我知道您应该使用 Id 作为密钥。但是现在必须这样做的方法是使用课程的标题作为关键字。

【问题讨论】:

在地图内不需要访问 course[index]。 course 已经包含与当前索引有关的值。就做 course.title 嗨,我遇到了我在帖子顶部提到的相同错误:index.js:1 Warning: Each child in a list should have a unique "key" prop. 你不需要索引来迭代数组。仅当您在数组中映射数组并需要检查某些条件时才使用该方法。@MA_Dev 给出正确的分析器。试试你也放key=index 看起来不错:codesandbox.io/s/infallible-germain-q6cze?file=/src/App.js 它很好。它只是输出到问题所在的页面。我在地图中有 console.log(course),它输出得很好。 【参考方案1】:

通过您的修改,我认为我们可以更有效地帮助您。对于将来,发布您的代码示例将是有益的 https://codesandbox.io/

另外为了在调试时帮助自己,将 react 组件与 redux 的使用隔离开来。这将允许你确保你的 react 组件在给定数据时呈现,然后专注于让 redux 为你提供你的 react 组件所拥有的数据。

您可以通过首先在您的 React 组件中定义模拟数据,然后将该模拟数据移动到您的减速器,最后用实时 api 调用替换模拟数据来做到这一点。

进入代码:

您有两个问题:第一个是您想要索引到数组 courses,但由于拼写错误,您实际上是在使用属性访问器到对象 course

key=course[index].title

正如您的问题所述,您必须使用标题作为键,只需将 div 更改为:

&lt;div key=course.title&gt;course.title&lt;/div&gt; 并且您的代码应该可以按预期工作。

一旦您解决了这个问题,然后使用 Redux 从您的 API 调用中重新启用加载数据,您就可以解决 Redux 的问题。

查看您的减速器,您有一个明显的错误,并且根据您的用例,一个潜在的错误:

case types.LOAD_COURSES_SUCCESS:
            return [...state,  ...action.courses ];

action.courses 是一个数组,代码正在创建一个新数组,其中包含先前数组state 的所有元素,并添加一个新对象,该对象包含解构后的array.courses 数组的内容。

这实际上是将单个对象附加到您的数组中,并且该对象由您的课程数组中的元素组成。项索引成为键,项本身就是值。

您可以在此处对其进行可视化:https://codesandbox.io/s/divine-pond-nr3j8

你想要的

return [...state, ...action.courses];

第二个潜在的错误是,您实际上是在附加课程 api 的结果。对于后续调用加载课程,您将复制数据。这可能是你想要的,但我会假设这不是你想要的。

因此,您的 LOAD_COURSES_SUCCESS 案例应该被重写为:

return [...action.courses];

【讨论】:

同样的错误:Warning: Each child in a list should have a unique "key" prop. 嗨艾伦,感谢您的建议和帮助。正如您正确指出的那样,问题出在减速器中。当我尝试return [...action.courses]; 它工作时,控制台中没有出现错误并且页面上加载了课程。感谢所有帮助过我的人。感谢您的所有帮助。【参考方案2】:

有很多方法可以在迭代时传递密钥...

var courses = this.state.courses.map(function(course, index) 
        return(
            <div key=index>
                <div key=course.title id=course.title>
                    <h2 key="header"+course.title>course.title</h2>
                </div>
            </div>
        )
    );

但是你应该尝试传递一个唯一的 id 而不是一个字符串。

【讨论】:

【参考方案3】:

这里是渲染方法的代码 sn-p。 试试看吧。

*更新 = 使用课程名称作为关键字

render() 
    const courseList = this.props.courses.map(course => (
        <div key=course.title></div>
    ));
        
    return (
        <>
            <h2>Courses</h2>
            <div>courseList</div>
        </>
    );

                

【讨论】:

同样的错误:Warning: Each child in a list should have a unique "key" prop.【参考方案4】:

问题就在这里:

this.props.courses.map((course, index) => (

                    <div key=course[index].title>course[index].title</div>


                ))
//course in itself is data

解决方案:

this.props.courses.map((course, index) => (

                    <div key=`$course.title-$index`>course.title</div>


                ))

更好的方法是始终注意密钥的唯一 ID

【讨论】:

嗨,我仍然遇到同样的错误:Warning: Each child in a list should have a unique "key" prop. 试试这个:$course.title-$index。更新了我的答案 现在我没有收到任何错误,但页面上没有加载任何数据。 我看不到任何错误。您可以交叉检查或更新此沙箱吗? codesandbox.io/s/quizzical-sun-trvki【参考方案5】:

由于每门课程都有唯一的 ID 字段,所以可以通过 id 作为 key 来解决问题

render() 
  return (
    <>
      <h2>Courses</h2>



      this.props.courses.map(course => (

        <div key=course.id>course.title</div>


      ))
    </>
  );

【讨论】:

同样的错误:Warning: Each child in a list should have a unique "key" prop. 那么courses 数组可能有问题。你试过打印courses吗? JSX 中的 JSON.stringify(this.props.courses) 之类的东西。这将有助于解决问题。 是的。它使用 JSON.stringify(this.props.courses) 打印得很好。它出现在页面上。我也在浏览器控制台打印出来了,没有任何问题。

以上是关于Map 在 React 中的第一次迭代后停止迭代的主要内容,如果未能解决你的问题,请参考以下文章

第一次迭代后循环停止

使用 .map() 在对象 React 中迭代数组

我正在尝试使用 c++ STL 制作 prims 算法。在迭代器第一次迭代后,它会停止代码并给出错误的输出

我的 do while 循环在一次迭代后停止。我该如何继续下去?

嵌套的while循环在第一次迭代PHP后停止

python -- 迭代器