1

I am new to React so I am just trying to pull data from my wordpress website API. I am getting a generic blog post which will display this.state.post.link fine but not any of the rendered data.

import React from 'react'

export default React.createClass({

  getInitialState: function () {
    return {
      post: {},
    }
  },

  componentDidMount: function () {
    var _this = this;
    $.get('http://somewebsite.net/wp-json/wp/v2/posts/1258', function(result) {
      _this.setState({
        post: result
      });
    });
  },

  render() {
    console.log(this.state.post);
    return <div className="single-post">
      <h1>{this.state.post.link}</h1>
      <h1>{this.state.post.title.rendered}</h1>
    </div>
  }
});

I get this error from adding post.title.rendered.

bundle.js:51835 Uncaught TypeError: Cannot read property 'rendered' of undefined

This is what shows with the code console.log(this.state.post.title);

Object {rendered: "Example post"}

So why can I console.log this.state.post.title and it shows the object with rendered in but then if I try and display that it will say title is undefined?

3 Answers 3

4

Define the initial state for title.rendered as a empty string.

this.state = {
  post: {
    title: {
      rendered: ''
    }
  }
...
render() {
  return (
    <div>
      {this.state.post.title.rendered}
    </div>
  )
}

OR

Check if the state is defined before rendering:

render() {
  return (
    <div>
      {this.state.post ? this.state.post.title.rendered : null }
    </div>
  )
}
Sign up to request clarification or add additional context in comments.

Comments

2

Reason is you are fetching the data from api, until you didn't get the data, this.state.post.title will be undefined, and you are trying to access rendered of undefined, that's why it is throwing the error:

Cannot read property 'rendered' of undefined

ajax call is asynchronous call, it will take time to fetch the data and render method will get called before that.

One solution is, put the check on this.state.post.title:

render() {
    console.log(this.state.post);
    return <div className="single-post">
      <h1>{this.state.post.link}</h1>
      <h1>{this.state.post.title && this.state.post.title.rendered}</h1>
    </div>
  }

Or hold the complete rendering until you didn't get the data, by putting the check on this.state.post inside render method.

Update-

Define the initial value of post as null:

getInitialState: function () {
    return {
      post: null,
    }
  },

Then check the value of post inside render method, it will not rendering anything until you didn't get the response:

render() {
    console.log(this.state.post);

    if(!this.state.post) return null;

    return <div className="single-post">
      <h1>{this.state.post.link}</h1>
      <h1>{this.state.post.title.rendered}</h1>
    </div>
}

Note: There is one issue with this, rendered key must be present inside title in response otherwise it will also throw the same error.

6 Comments

Ok cool, so how do I defer the render method until the data is loaded? That seems like the best solution to me
@Callum check the updated answer for that, return null until you didn't get the data, it will work :)
Hi thankyou, setting the initial value for post to null worked for me. So if it returns null the first time in the render method, does that mean it gets called twice?
yes, as many times you use setState it will triggered the render method, and do the change in DOM, that's how reactjs works, check the doc : facebook.github.io/react/docs/react-component.html#setstate
Ok thankyou and can a 404 be set in the componentDidMount method somehow if a 404 is returned form the ajax call?
|
0

maybe this will be helpful:

render() {
    console.log(this.state.post);
    var link = (this.state.post && this.state.post.link) ? this.state.post.link : '';
    var rendered = (this.state.post && this.state.post.title && this.state.post.title.rendered) ? this.state.post.title.rendered : '';

    return <div className="single-post">
      <h1>{link}</h1>
      <h1>{rendered}</h1>
    </div>
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.