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 更改为:
<div key=course.title>course.title</div>
并且您的代码应该可以按预期工作。
一旦您解决了这个问题,然后使用 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 中的第一次迭代后停止迭代的主要内容,如果未能解决你的问题,请参考以下文章
我正在尝试使用 c++ STL 制作 prims 算法。在迭代器第一次迭代后,它会停止代码并给出错误的输出