shreyaa
shreyaa

Reputation: 93

use axios with react to get data from api

I am trying to use axios to get data from the api (https://reqres.in/) and display in my react app. Before this I fetched the data from the API using fetch method in javascript. Now I have tried coding this from various resources. How should I do it. Is it the correct method?

My app.js file-

import React, { Component } from 'react';
import './App.css'; 
import axios from 'axios';

class App extends Component {
  constructor(props) {
    super(props);
  this.successShow = this.successShow.bind(this);
  this.errorShow = this.errorShow.bind(this);
}
componentDidMount() {
 axios.get('https://reqres.in/api/products/3')
   .then(function (response) {
     this.successShow(response);
   })
   .catch(function (error) {
     this.errorShow(error);
   });
 }
successShow(response) {
 this.member = <pre>{JSON.stringify(response.data, null, '\t')}</pre> ;
}
errorShow(error) {
 this.member = <pre>{JSON.stringify(error.response.data, null, '\t')}</pre>;
}
render() {
  return (
    <div>
      <h2>Welcome to React</h2>
      <h3>{JSON.stringify(this.state.person.data)}</h3>
      <div>{this.member}</div>
    </div>
  );
  }
 }
export default App;

It also gives the error - Unhandled Rejection (TypeError): Cannot read property 'errorShow' of undefined.

Upvotes: 1

Views: 3320

Answers (4)

Mayank Shukla
Mayank Shukla

Reputation: 104499

Changes:

1. You need to bind this with then and catch callback methods, use arrow functions.

2. You didn't define the initial state and using this.state.person.data it will throw error.

3. Storing the UI in state or global variable is not a good idea, ui part should be inside render method only.

Write it like this:

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            person: {}
        }
        //this.successShow = this.successShow.bind(this);
        //this.errorShow = this.errorShow.bind(this);
    }

    componentDidMount() {
        axios.get('https://reqres.in/api/products/3')
        .then((response) => {
            this.successShow(response);
        })
        .catch((error) => {
            this.successShow(error);
        });
    }

    successShow(response) {
        this.setState({
            person: response.data
        });
    }

    render() {
        return (
            <div>
              <h2>Welcome to React</h2>
              <h3>{JSON.stringify(this.state.person.data)}</h3>

              <pre>{JSON.stringify(this.state.person.data)}</pre>

              <div>{this.member}</div>
            </div>
        );
    }
}

Upvotes: 3

TomW
TomW

Reputation: 4002

The problem is that the this in your then and catch callbacks doesn't refer to your class, but to the default (global) scope. You need to bind the right this. You actually already have the appropriate functions set up with this binding, so you can just use them directly:

componentDidMount() {
  axios.get('https://reqres.in/api/products/3')
   .then(this.successShow)
   .catch(this.errorShow);
}

In general, you can also use => function syntax, which inherits the 'this' from the scope the function is declared in, rather than using the global scope. E.g.

componentDidMount() {
  axios.get('https://reqres.in/api/products/3')
   .then(success => this.successShow(success))
   .catch(error => this.errorShow(error));
}

(note the => functions are completely unnecessary here of course).

You have an additional problem, which is the you need to store member in component state (this.state.member), not just as a field, and use the setState function to update it. Otherwise your component won't re-render when you update member.

Upvotes: 1

Nocebo
Nocebo

Reputation: 2017

Try this:

componentDidMount() {
 axios.get('https://reqres.in/api/products/3')
   .then((response) => {
     this.successShow(response);
   })
   .catch((error) => {
     this.errorShow(error);
   });
 }

Use arrow functions to remain the right scope of this

Upvotes: 1

Maxim Kuzmin
Maxim Kuzmin

Reputation: 2614

When you call this.errorShow() inside of the function, this is not your component object, but context of function. You should use arrow functions instead, arrow functions do not create its own this so you can access your component this:

componentDidMount() {
 axios.get('https://reqres.in/api/products/3')
   .then((response) => {
     this.successShow(response);
   })
   .catch(error) => {
     this.errorShow(error);
   });
 }

More info about arrow functions

Upvotes: 2

Related Questions