简体   繁体   中英

TypeError: Cannot read property 'map' of undefined React-Redux

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM