简体   繁体   中英

React.js - Loading single post data from API correctly

I am fairly new to React, and trying to work my way through how I should properly be loading data from my API for a single post.

I have read that I should be using "componentDidMount" to make my GET request to the API, but the request is not finished by the time the component renders. So my code below does not work, as I am recieving the error: "Cannot read property setState of undefined".

What I am doing wrong here? Should I be calling setState from somewhere else? My simple component is below - thanks.

import React from 'react';
import Header from './Header';
import axios from 'axios';

class SingleListing extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            listingData: {}
        }
    }

    componentDidMount() {

        // Get ID from URL
        var URLsegments = this.props.location.pathname.slice(1).split('/');

        // Load the listing data
        axios.get('/api/listing/' + URLsegments[1])
            .then(function(res){

                let listingDataObject = res.data;
                console.log(listingDataObject);
                this.setState({
                    listingData: listingDataObject
                });

            })
            .catch(function(err){
                console.log(err);
            });

    }


    render() {

        console.log('helsdfdsfsdflssosso');
        console.log(this.state.listingData);

        return (
            <div className="SingleListing">
                <Header />
                <div className="container">

                    <div>Property Address: {this.state.listingData.propertyAddress}</div>
                    This is a single listing
                </div>
            </div>
        )
    }

}
export default SingleListing;

You just need to change what you render depending on whether the data is loaded or not yet.

Also, you should use arrow functions when handling the axios response, otherwise this is not set correctly.

class SingleListing extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      listingData: null,
    };
  }

  componentDidMount() {
    // Get ID from URL
    const URLsegments = this.props.location.pathname.slice(1).split('/');

    // Load the listing data
    axios
      .get(`/api/listing/${URLsegments[1]}`)
      .then(res => {
        const listingDataObject = res.data;
        console.log(listingDataObject);
        this.setState({
          listingData: listingDataObject,
        });
      })
      .catch(err => {
        console.log(err);
      });
  }

  render() {
    const isDataLoaded = this.state.listingData;

    if (!isDataLoaded) {
      return <div>Loading...</div>;
    }

    return (
      <div className="SingleListing">
        <Header />
        <div className="container">
          <div>Property Address: {this.state.listingData.propertyAddress}</div>
          This is a single listing
        </div>
      </div>
    );
  }
}

export default SingleListing;

this is out of scope you need to include it. here is a solution using es2015 arrow functions =>

axios.get('/api/listing/' + URLsegments[1])
        .then((res) => {
            let listingDataObject = res.data;
            console.log(listingDataObject);
            this.setState({
                listingData: listingDataObject
            });

        })
        .catch((err) => {
            console.log(err);
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM