我的组件应该在安装组件时检索类(class)数据。我遇到的问题是,无论我使用类(class) ID 还是类(class)标题作为键,我都会收到以下错误:
index.js:1 Warning: Each child in a list should have a unique "key" prop.
我查看了 Stack Overflow 上的 React 文档,并尝试了不同的方法来让它工作。我能让它部分工作的唯一方法是添加一个索引作为 map 的参数。当我使用这种方法时,我遇到了另一个问题,即它在第一次迭代后停止,即使有 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 作为 key 。但目前必须采用的方法是使用类(class)标题作为 key 。
最佳答案
通过您的修改,我认为我们可以更有效地帮助您。对于 future ,发布一个您的代码示例在 https://codesandbox.io/ 上不起作用将是有益的
另外,为了在调试时帮助自己,将 react 组件与 redux 的使用隔离开来。这将允许您确保您的 React 组件在给定数据时呈现,然后专注于让 redux 为您提供您的 React 组件所拥有的数据。
您可以通过首先在您的 React 组件中定义模拟数据,然后将该模拟数据移动到您的 reducer,最后用实时 API 调用替换模拟数据来做到这一点。
关于代码:
你有两个问题:第一个是你想索引数组 courses
但由于打字错误,您实际上是在对象中使用属性访问器 course
key={course[index].title}
正如您的问题所述,您必须使用标题作为键,只需将 div 更改为:
<div key={course.title}>{course.title}</div>
并且您的代码应该按预期工作。
一旦你解决了这个问题,然后使用 Redux 重新启用从你的 API 调用加载数据,你就可以解决 Redux 的问题。
看看你的 reducer ,你有一个明显的错误,并且根据你的用例,一个潜在的错误:
case types.LOAD_COURSES_SUCCESS:
return [...state, { ...action.courses }];
action.courses
是一个数组,代码正在创建一个新数组,其中包含前一个数组的所有元素 state
并添加一个新对象,其中包含解构 array.courses
的内容数组。
这样做实际上是将单个对象附加到您的数组,并且该对象由类(class)数组中的元素组成。项目索引成为键,项目本身就是值。
您可以在此处可视化它:https://codesandbox.io/s/divine-pond-nr3j8
相反,你想要
return [...state, ...action.courses];
第二个潜在错误是您实际上是在附加类(class) api 的结果。对于后续加载类(class)的调用,您将复制数据。这可能是您想要的,但我假设这不是您想要的。
因此,您的 LOAD_COURSES_SUCCESS
case 应该重写为:
return [...action.courses];
关于javascript - map 在 React 中的第一次迭代后停止迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63609452/