Jakub Kašpar
Jakub Kašpar

Reputation: 285

Cannot convert undefined or null to object in react

I am trying to map object properties from initial state object. I can get all properties except the nested milesotnes.

The initial state is defined in components class constructor like so:

class GoalView extends Component {
  constructor(props) {
    super(props);

    this.state = {
      dataGoal: {},
      uid: firebaseAuth().currentUser.uid,
      currentGoalId: this.props.match.params.goalId,
    };
  }

  componentDidMount = () => {
    const dataGoalRef = dbRef.child('goals/'+this.state.uid+'/'+this.state.currentGoalId);
    dataGoalRef.on('value', snap => {
        this.setState({
          dataGoal: snap.val(),
          currentGoalId: this.props.match.params.goalId,
        });
    });
  }

  componentWillUnmount = () => {
    this.state = {
      currentGoalId: null,
    };
  }
  
  ...
  
}

I am getting the currentGoalId from a React Router V4 Link:

<Link title="Open goal" to={"/app/goal/id"+key}>Open goal</Link>

which is in a higher order component. The render method of the current GoalView component looks like so:

  render() {
    return(
      <div>
        <main className="content">
          <p>{this.state.dataGoal.description}</p><br /><br />

            {Object.keys(this.state.dataGoal.milestones).map( (milestoneKey) => {
              const milestonesData = this.state.dataGoal.milestones[milestoneKey];

              return <div className="milestone-wrap" key={milestoneKey}>
                       <label className="milestone-label truncate">{milestonesData.name}</label>

                     </div>
            })}

        </main>
      </div>
    );
  }
}

and the state:

enter image description here

I am getting Cannot convert undefined or null to object from this row {Object.keys(this.state.dataGoal.milestones).map( (milestoneKey) => {...}

but the description in render method right above that row is rendering just fine. Anyone has some ideas, please?

Thank you, Jakub

Upvotes: 6

Views: 31677

Answers (1)

Mayank Shukla
Mayank Shukla

Reputation: 104539

Before using Object.keys() put the check on dataGoal, like this:

this.state.dataGoal.milestones && Object.keys(this.state.dataGoal.milestones)

Reason: You are fetching the data from server it will take time, until that this.state.dataGoal.milestones will be undefined.

Or you can hold the rendering until you didn't get the data by using a bool in state variable.

Check this, it will produce the same error:

let a = {};

Object.keys(a.a).map(el => console.log(el));

Suggestion: Binding of lifecycle methods are not required, use them directly, so remove the arrow function with lifecycle methods.

Upvotes: 22

Related Questions