MiniGunnR
MiniGunnR

Reputation: 5800

Why does React fetch retrieve blank object?

I have a working Django REST API which returns this:

{
    "id": 1,
    "brand": "peugeot",
    "model": "3008",
    "variant": "allure"
}

I am using the following code to fetch the above data:

render() {
        const { brand, model, variant } = this.props;
        let url = `http://127.0.0.1:8000/api/car/${brand}/${model}/${variant}/`;
        console.log(url) <== url is correct when checked in console
        fetch(url)
            .then(response => response.json())
            .then(data => data.length === 0 ? this.setState({
                data : data
            }) : null ) <== I have used a condition for setState to stop fetching infintely

        const { data } = this.state;
        console.log(data) <== This is a blank object with no data in console
        console.log(data.id) <== This is undefined in console
        return (
            <div>
                {data.id} <== No data is shown on webpage
                Car Details
            </div>
        );
    }

No error is shown when I try to fetch the data on my webpage. What am I doing wrong?

P.S. Data can be fetched from the same API server when I have an array of objects, and I use map to loop over the data. Over here I am trying to fetch a single item so there is no array, just an object. Am I doing something wrong with the syntax?

Upvotes: 0

Views: 222

Answers (3)

Dor Weid
Dor Weid

Reputation: 454

You should never fetch or setState inside the render function.

render is called many times due to all kinds of side effects, i.e scrolling, clicking, props changing etc. This kind of code could cause all kinds of trouble.

If you need to perform the request once, call the fetch function inside componentDidMount. Also, I believe your callbacks should look something like this:

fetch(url)
  .then(response => response.json())
  .then(data => this.setState({ data : data }))

Taken from the docs:

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.

Upvotes: 3

MiniGunnR
MiniGunnR

Reputation: 5800

I changed the condition before 'setState' to JSON.stringify(data) !== JSON.stringify(this.state.data) and now it works.

Upvotes: 1

Jee Mok
Jee Mok

Reputation: 6556

should it be:

.then(data => data.length > 0 ? this.setState({ data }) : null )

Upvotes: 0

Related Questions