Search code examples
javascriptreactjswordpress-rest-apiheadless-cms

Uncaught TypeError: Cannot read properties of undefined (reading 'rendered')


im newbie in React and trying to make a headless worpdpress aplication. when i fetch a post i get only the first value.

I fetch the post and save it in the state

componentDidMount() {
this.setState({ loading: true }, () => {
  axios.get('http://localhost/wpprojekte/ebike/wp-json/wp/v2/posts/426')
    .then(res => {
      this.setState({ loading: false, error: 'no error', post: res.data })
    }).catch(error => {
      console.log(error);
    });
});}

I have now the post in my state which looks like

constructor(props) {
super(props);
this.state = {
  loading: false,
  error: 'error',
  post: {},
}}

when i render the Component, i can get only the first value from the post. for example this.state.post.date

when i try to get this.state.post.title.rendered

Uncaught TypeError: Cannot read properties of undefined (reading 'rendered')

here is The render function

render() {
console.log(JSON.stringify(this.state.post));
return (
  <div>
    {<div dangerouslySetInnerHTML={{ __html: this.state.post.title.rendered }} />}
  </div>
)}

I dont understand why it is getting only the first value.

this is the console log

  "id": 426,
  "date": "2021-05-07T09:49:37",
  "date_gmt": "2021-05-07T09:49:37",
  "guid": {
    "rendered": "http://localhost/wpprojekte/ebike/?post_type=genusstouren&#038;p=426"
  },
  "modified": "2021-11-30T11:00:28",
  "modified_gmt": "2021-11-30T11:00:28",
  "slug": "schoeningen-helmstedt",
  "status": "publish",
  "type": "genusstouren",
  "link": "http://localhost/wpprojekte/ebike/genusstouren/schoeningen-helmstedt/",
  "title": {
    "rendered": "Genuss Bike Paradies Etappe 10"
  },
  "content": {
    "rendered": "\n<p><strong>Diese Etappe startet in Schöningen und führt am Lappwaldsee durch Helmstedt und den angrenzenden Lappwald nach Wolfsburg.</strong></p>\n\n\n\n<p>Die Route beginnt am Burgplatz nahe des Schlosses Schöningen und führt am ehemaligen Tagebau entlang in Richtung Norden. Dort führt die Tour westlich am Lappwaldsee entlang nahe des Grenzübergangs Helmstedt/Marienborn, welcher der größte und bedeutendste Grenzübergang an der innerdeutschen Grenze war. Von Helmstedt aus, in dessen Altstadt noch immer Teile der Stadtmauer als Wallanlagen zu finden sind, folgt die Route dem Lappwald, führt durch bewaldetes Gebiet und am Kloster Mariental durch Grasleben wieder in westlichere Richtung. Über Feldwege und durch kleinere Ortschaften geht es nach Velpke und von dort aus durch die Velpker Schweiz nach Oebisfelde. Nach Grafhorst und Überquerung der Aller führt die Route am Naturschutzgebiet Wendschotter und Vorsfelder Drömling entlang nach Wolfsburg, wo die Etappe am Wissenschaftsmuseum phaeno endet.</p>\n\n\n\n<p></p>\n\n\n\n<script type=\"text/javascript\" src=\"https://regio.outdooractive.com/oar-harz/de/embed/55540446/js?mw=false\"></script>\n",
    "protected": false
  },
  "excerpt": {
    "rendered": "<p>Diese Etappe startet in Schöningen und führt am Lappwaldsee durch Helmstedt und den</p>\n<div class=\"mehr-erfahren\"><a href=\"http://localhost/wpprojekte/ebike/genusstouren/schoeningen-helmstedt/\" rel=\"nofollow\"><icon class=\"fas fa-angle-double-right\"></icon> mehr erfahren</a></div>\n",
    "protected": false
  },
  "author": 2,
  "featured_media": 442,
  "parent": 0,
  "menu_order": 0,
  "template": "",
  "meta": [],
  "featured_image_src": "http://localhost/wpprojekte/ebike/wp-content/uploads/2021/05/Etappe_10.jpg",
  "_links": {
    "self": [
      {
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/genusstouren/426"
      }
    ],
    "collection": [
      {
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/genusstouren"
      }
    ],
    "about": [
      {
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/types/genusstouren"
      }
    ],
    "author": [
      {
        "embeddable": true,
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/users/2"
      }
    ],
    "version-history": [
      {
        "count": 3,
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/genusstouren/426/revisions"
      }
    ],
    "predecessor-version": [
      {
        "id": 1065,
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/genusstouren/426/revisions/1065"
      }
    ],
    "wp:featuredmedia": [
      {
        "embeddable": true,
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/media/442"
      }
    ],
    "wp:attachment": [
      {
        "href": "http://localhost/wpprojekte/ebike/wp-json/wp/v2/media?parent=426"
      }
    ],
    "curies": [
      {
        "name": "wp",
        "href": "https://api.w.org/{rel}",
        "templated": true
      }
    ]
  }
}


Solution

  • SOLUTION

    The reason you are getting the error is because componentDidMount is called after your render method is called that is your UI is rendered before your post is fetched, how does it relate to the error ? Now this is it. from your code calling this.state.post.date returns null which is empty and doesnt cause any issue because from react lifecycle render method is called first before componentDidMount but calling this.state.post.title.rendered when post is not fetched or is not available on state does the following, first it checks this.state.post.title which is null which could just work as that of the date but calling .rendered on the null will now throw the error you are getting. to make sure you dont get into such error you have to make sure title is defined or post is set on state

    CODE SOLUTION

    replace your render with this one.

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