0

I keep getting undefined for this.props.data when I have passed it from by setting this.state this.props.data from last component.

Here is the jobOffer component which properly passes data and render:

const JobOffer = React.createClass({
  mixins: [Navigation],

  getInitialState: function() {
    console.log(this.props.data);
    return {
        listing: this.props.data
    };
  },

  componentDidMount: function() {
    AppStore.addChangeListener(this._onChange);
  },


    _onChange : function(){
      this.setState({listingDetail:this.state.listing});
    },


  handleClick: function () {
    this.transitionTo('/listing/' + this.state.listing.id );
  },


  render: function () {
      var data = this.state.listing;
      var employmentType;
      switch(data.employment_type) {
        case 'F':
            employmentType = 'Full Time';
            break;
        case 'P':
            employmentType = 'Part Time';
            break;
        case 'H':
            employmentType = 'Hourly';
            break;
        default:
            employmentType = 'Unknown';
      }
      return (
        <a onClick={this.handleClick}>
            <img style={{width: 50+'px', height: 50+'px'}} src="images/job1.jpg" alt="" className="img-circle" />
            <div className="title">
                <h5>{data.job_title}</h5>
                <p>{data.Business.business_name}</p>
            </div>
            <div className="data">
                <div ><i>Posted 1 Day Ago</i></div>
                <div className="city"><i className="fa fa-map-marker"></i>{data.Business.business_city}</div>
                <div className="type full-time"><i className="fa fa-clock-o"></i>{employmentType}</div>
                <div className="sallary"><i className="fa fa-dollar"></i>{data.job_compensation}</div>
            </div>
        </a>

      );
    },

});


module.exports = JobOffer;

You can see that I am passing listingDetail when _onChange. Here is the jobDetails component that is is giving the undefined error.

var React = require('react');
var ReactBootstrap = require('react-bootstrap');
var Button = ReactBootstrap.Button;
var Modal = ReactBootstrap.Modal;
var AppActions = require('../actions/app-actions');
var AppStore = require('../stores/app-store');
var Navigation = require('react-router').Navigation;
var _ = require('lodash');

var JobOffer = require('./JobOffer');


// Our custom component is managing whether the Modal is visible
const ListingDetail = React.createClass({
  mixins: [Navigation],

  getInitialState: function() {
    console.log(this.props.data);
    return {
        ListingDetail: this.props.data
    };
  },

  componentDidMount: function() {
    AppStore.addChangeListener(this._onChange);
  },


  _onChange : function(){

  },


  handleClick: function () {
    this.transitionTo('/listing/apply/' + this.state.ListingDetail.id );
  },


  render: function () {
      var data = this.state.ListingDetail

      return (
            <img style={{width: 200+'px', height: 200+'px'}} src="images/job1.jpg" alt="" className="img-circle" />
            <div className="title">
                <h5>{data.job_title}</h5>
                <p>{data.Business.business_name}</p>
            </div>
                <div className="city"><i className="fa fa-map-marker"></i>{data.Business.business_city}</div>
                <div className="type full-time"><i className="fa fa-clock-o"></i>{employmentType}</div>
                <div className="sallary"><i className="fa fa-dollar"></i>{data.job_compensation}</div>

            <div className="container">
              <div className="row">
                <div className="col-sm-8">
                  <h3></h3>

                  <article>
                    <h2>Job Details</h2>
                    <p>{data.job_description}</p>

                  </article>
                </div>

      );
    },

});


module.exports = ListingDetail;

Any idea?

rahul2001
  • 1,577
  • 2
  • 17
  • 32
  • `this._onChange.bind(this)` – zerkms Jul 09 '15 at 23:40
  • where? In componentDidMount in JobOffer? – rahul2001 Jul 09 '15 at 23:51
  • Everywhere. PS: it worth trying before you ask next time – zerkms Jul 09 '15 at 23:52
  • when adding .bind(this) got : Warning: bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call. See JobOffer ListingDetail.js:18 undefined ListingDetail.js:47 Uncaught TypeError: Cannot read property 'job_title' of undefined – rahul2001 Jul 09 '15 at 23:58
  • So? It's a different problem with your code already. – zerkms Jul 10 '15 at 00:04
  • `var data = this.state.listing;` --- why do you think `this.state.listing` is defined? – zerkms Jul 10 '15 at 00:06
  • in JobOffer? Its defined because it's passed from a JobListings componente `const JobsListing = React.createClass({ mixins: [Navigation], getInitialState: function() { return { listings: [] }; }, componentDidMount: function() { AppStore.addListingChangeListener(this._onChange); AppStore.getListings(true); }, _onChange : function(){ this.setState({listings:AppStore.getListings()}); },` which is working. Only thing not working is ListingDetails – rahul2001 Jul 10 '15 at 00:15
  • `this.setState({listingDetail:this.state.listing});` --- here you replace the state with an object that does not have `listing` property. So, why do you think `this.state.listing` should be defined? – zerkms Jul 10 '15 at 00:17
  • Well what im trying to do is pass the data _onChange of the listing – rahul2001 Jul 10 '15 at 00:39
  • Yep, but the new state's structure is different from old. :-S Not sure what your current problem is and why it confuses you. – zerkms Jul 10 '15 at 00:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82878/discussion-between-rahul2001-and-zerkms). – rahul2001 Jul 10 '15 at 00:48
  • As far as I know, `setState` does not replace the current state object with the one provided as an argument, but rather shallowly merges the two. – Hannes Johansson Jul 13 '15 at 10:48

1 Answers1

0

I don't see that neither JobOffer nor ListingDetail is being rendered anywhere. Which component is going to render which?

The this.props property of any component is going to contain any properties that were passed to the component at the point it was rendered (or rather "mounted", in React's component lifecycle terminology). It's not meant to be mutated during the component's lifespan, so you can view them as "initialization" values. The this.state property of a component on the other hand should contain properties that do change throughout the component's lifecycle, and each time you change it by using this.setState() the component will be re-rendered (unless you prevent a re-render in the this.shouldComponentUpdate method) to reflect the new state.

So, this.props contains any values that you passed as "attributes" when mounting the component. If you use JSX it could look something like this:

var Parent = React.createClass({
    render: function() {
        return <DetailsListing id={123} job_title="React Dev" />;
    }
});

In this case, DetailsListing's this.props.id is 123 and this.props.job_title is "React Dev" as expected.

You seem to confuse the difference between state and props by returning props as an initial state. Props should be props and state should be state, not intermixed (this might be opinionated, but I think it's definitely mandated by the React principles). Either way, this.props will only contain the values that you passed it when rendering/mounting.

Hannes Johansson
  • 1,794
  • 2
  • 15
  • 28