I am learning Redux
from https://app.pluralsight.com/library/courses/react-redux-react-router-es6/table-of-contents but I am stuck at some point. When I am trying to map my courses in CoursePage.js
then it is showing this error, The prop courses
is marked as required in CoursesPage
, but its value is undefined
. and:
Uncaught TypeError: Cannot read property 'map' of undefined.
Here's the code
CoursePage.js
import React, { Component } from "react";
import { connect } from "react-redux";
import * as courseAction from "../../redux/actions/courseAction";
class CoursePage extends Component {
constructor(props) {
super(props);
console.log(this);
this.state = {
course: {
title: "",
},
};
}
handleChange = (event) => {
const course = { ...this.state.course, title: event.target.value };
this.setState({ course });
};
handleSubmit = (event) => {
event.preventDefault();
this.props.createCourse(this.state.course);
// alert(this.state.course.title);
};
render() {
return (
<main>
<div className="container">
<div className="jumbotron jumbotron-fluid">
<div className="container">
<h1 className="display-4">Course Page</h1>
<form className="mt-4" onSubmit={this.handleSubmit}>
<input
type="text"
onChange={this.handleChange}
value={this.state.course.title}
/>
<input type="submit" value="Add" />
{this.props.course.map((course) => (
<div key={course.title}>{course.title}</div>
))}
</form>
</div>
</div>
</div>
</main>
);
}
}
function mapStateToProps(state) {
return {
course: state.course,
};
}
function mapDispatchToProps(dispatch) {
return {
createCourse: (course) => dispatch(courseAction.createCourse(course)),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(CoursePage);
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 }];
default:
return state;
}
}
The state called this.state.course
is an {}
and that's the reason why you cannot run .map()
on it. It can handle arrays only. Instead probably you want to show up title
for the course then you don't need .map()
.
Try the following only:
<div>{this.state.course.title}</div>
I hope this helps!
You've got a few minor issues here, that need fixing to bring you on the right track.
Your mapStateToProps
refers to course
, not courses
. And if you want it to refer to courses
then you need to update how the CREATE_COURSE
action works in your reducer.
To fix the crash causing bug you'll need to add an initialState
so that courses
isn't undefined. Since it's ok to map through an empty array, but you can't map through undefined
.
Update your courseReducer
to the following:
import * as types from "../actions/actionTypes";
const initialState = {
courses: []
}
export default function courseReducer(state = initialState, action) {
switch (action.type) {
case types.CREATE_COURSE:
return { ...state, courses: [...state.courses, action.course] };
default:
return state;
}
}
And then make this change to your mapStateToProps
:
function mapStateToProps(state) {
return {
courses: state.courses,
};
}
Finally change this bit of code from this.props.course
to this.props.courses
:
{this.props.courses.map((course) => (
<div key={course.title}>{course.title}</div>
))}
Now your app should work as intended.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.