Kelb56
Kelb56

Reputation: 657

Undefined props in componentDidMount

This is starting to get really frustrating. Basically, I cannot access props in my subcomponents. if I try to render them directly using this.props- it works, but if I need to do additional processes with them, or save them into state, I get undefined props all the time. I have a parent component, which looks something like this:

import React from 'react';

import Title from './EventSubComponents/Title';
import SessionInfo from './EventSubComponents/SessionInfo';
import SessionTime from './EventSubComponents/SessionTime';
import Location from './EventSubComponents/Location';
import Subscribers from './EventSubComponents/Subscribers';

class EventNode extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      'event': [],
    }
  }

  componentDidMount() {
    this.getEvent(this.props.location.selectedEventId);
  }

  getEvent(eventId) {
    fetch('/api/v.1.0/event/' + eventId, {mode: 'no-cors'})
      .then(function(response) {
        if(!response.ok) {
          console.log('Failed to get single event.');
          return;
        }
        return response.json();
      })
      .then((data) => {
        if (!data) {
          return;
        }
        this.setState({
          'event': data
        })
      });
  }

  render() {
    return(
      <div className="event-wrapper">
        <Title 
        title = { this.state.event.title } 
        date = { this.state.event.start }
        />
        <SessionInfo 
          distance = { this.state.event.distance }
          type = { this.state.event.type }
        />
        <SessionTime 
          start = { this.state.event.start }
          end = { this.state.event.end }
        />
        <Location location = { this.state.event.start_location }/>
        <Subscribers 
        subscribers = { this.state.event.subscribers } 
        eventId = { this.state.event._id }
        />
      </div>
    );
  }
}

export default EventNode;

And my sub-component SessionTime, which looks like this:

import React from 'react';
import moment from 'moment';

class Title extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      'title': '',
      'date': '',
    }
  }

  componentDidMount() {
    console.log(this.props.title);
    console.log(this.props.date);
    // undefined both props.
    this.convertToTitleDate(this.props.date);
    this.setState({
      'title': this.props.title
    })
  }

  convertToTitleDate(date) {
    var newDate = moment(date).format('dddd, Do MMMM')
    this.setState({
      'date': newDate,
    });
  }

  render() {
    return (
      <div className="event-title-wrapper">
        <h1> { this.state.title } </h1>
        <div className="event-title-date"> { this.state.date } </div>
      </div>
    );
  }
}

export default Title;

Could anyone explain, why both this.props.date and this.props.title are undefined in my componentDidMount function? I have couple more components in my EventNode and I have the same problems in them as well.

Changing componentDidMount to componentWillMount does not help. I am fairly certain I have problems in my parent EventNode component, but I cannot figure out where. Inside EventNode render() all the state variables are defined.

Upvotes: 3

Views: 7122

Answers (1)

Tholle
Tholle

Reputation: 112787

You initialize event to an empty array and pass down this.state.event.start and this.state.event.end to SessionTime, which will both be undefined on first render since event has not been loaded yet and there are no start and end properties on the array.

You could instead e.g. set event to null initially, and return null from the render method until the event has been loaded.

Example

class EventNode extends React.Component {
  state = {
    event: null
  };

  // ...

  render() {
    const { event } = this.state;

    if (event === null) {
      return null;
    }

    return (
      <div className="event-wrapper">
        <Title title={event.title} date={event.start} />
        <SessionInfo distance={event.distance} type={event.type} />
        <SessionTime start={event.start} end={event.end} />
        <Location location={event.start_location} />
        <Subscribers
          subscribers={event.subscribers}
          eventId={this.state.event._id}
        />
      </div>
    );
  }
}

Upvotes: 2

Related Questions