简体   繁体   中英

I'm getting a Cannot read property of 'exercises' of undefined error when trying to map my props

Here's my "database" that I'm using,

index.js:

const workoutPlan = {
  ID: 1,
  Name: "My Workout Plan",
  workout: {
    day: "Monday",
    exercises: [
      {
        Name: "Bench Press",
        sets: [
          {
            set: 1,
            weight: 135,
            rep: 10
          },
          {
            set: 2,
            weight: 145,
            rep: 8
          }
        ]
      },

      {
        Name: "Deadlift",
        sets: [
          {
            set: 1,
            weight: 135,
            rep: 10
          },
          {
            set: 2,
            weight: 145,
            rep: 8
          }
        ]
      }
    ]
  }
};

Which then in my WorkoutPlan.js file, I'm passing the properties of the workoutPlan to my Workout.js child.

WorkoutPlan.js:

import React from "react";
import Workout from "./Workout";
import axios from "axios";

class WorkoutPlan extends React.Component {
  constructor() {
    super();
    this.state = {
      workoutPlan: {}
    };
  }

  componentDidMount() {
    axios
      .get("/api/workout-plan")
      .then(response => {
        this.setState({ workoutPlan: response.data });
      })
      .catch(error => {
        console.log(error);
      });
  }

  render() {
    const { workoutPlan } = this.state;
    // const workoutPlan = this.state.workoutPlan;

    return (
      <div>
        <h1>{workoutPlan.Name}</h1>
        <Workout workout={workoutPlan.workout} />
      </div>
    );
  }
}

export default WorkoutPlan;

In my Workout.js file, I'm trying to only map the exercises property of WorkoutPlan.workout.exercises. However, when I run this code, I'm running into a TypeError: Cannot read property 'exercises' of undefined

What am I doing wrong in this Child?

Workout.js:

import React from "react";
import Exercise from "./Exercise";

// const Workout = props => {
//   props.workout.exercises.map(exercises => {
//     return (
//       <div>
//         <h2>"Workout for {props.day}"</h2>
//         <Exercise exercises={exercises} />
//       </div>
//     );
//   });
// };

function Workout(props) {
  props.workout.exercises.map(exercises => {
    return (
      <div>
        <h2>"Workout for {props.day}"</h2>
        <p>{exercises.Name}</p>
        <Exercise exercises={exercises} />
      </div>
    );
  });
}

export default Workout;

I've commented out the const, as I'm told that they're both methods are interchangeable. But if someone could actually provide some insight on how to do it on both methods, I'd be so grateful. The error is specifically referring to

  props.workout.exercises.map(exercises => {

in my Workout.JS file

On the first render, the props.workout value passed to the Workout is undefined because looking in the parent component WorkoutPlan the default value for this.state.workoutPlan is {} so calling workoutPlan.workout will be `undefined.

There are two approaches, in the parent don't render this component if the value is undefined . Or, in the child, handle the value of undefined .

Handling in the parent:

  render() {
    const { workout } = this.state.workoutPlan;

    return (
      <div>
        <h1>{workoutPlan.Name}</h1>
        {workout && <Workout workout={workout} />}
      </div>
    )
  }

Or, in the child:

function Workout(props) {
  // Early return if falsy value is passed (eg: undefined, null)
  if (!props.workout) return null;

  return props.workout.exercises.map(exercises => {
    return (
      <div>
        <h2>"Workout for {props.day}"</h2>
        <p>{exercises.Name}</p>
        <Exercise exercises={exercises} />
      </div>
    );
  });
}

Note, you also need to return the props.workout.exercises.map value.

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