简体   繁体   中英

Setting response from axios to state

When I try to setState after the get axios request it doesn't seem that I have the data ready to render.In console, I am getting a response but unable to access the response in the state.

import React, { Component } from 'react';
import axios from 'axios';
import { Grid, Row, Col } from 'react-flexbox-grid';
import Avatar from '@material-ui/core/Avatar';
import Button from '@material-ui/core/Button';
import stylefile from './stylefile';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { withStyles } from '@material-ui/core/styles';
import '../App.css';

class TitleBar extends Component {
    constructor() {
        super();
        this.state ={
            data:[],
        }
      }

    componentDidMount() {
        axios.get('http://api.abc',
            {
                headers: { "Postman-Token": "abc"}
            })
            .then((response) => {
                console.log(response.data);
                this.setState({
                    data: response.data,
                })
            })
            .catch((error) => {
                console.log(error)
            })
    }

  render() {
    const { classes } = this.props;
    console.log(this.state.data,"data response")
    return (
        <div>
            {
                this.state.data.map(((item,key) => (
                 <div>
                     //
                 </div>
             )))}
        </div>
    );
  }
}

export default withStyles(stylefile)(TitleBar);
          console.log(error);
        });
    }

//console.log(this.state.data) -- is undefined

From React official docs ,

componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering

Also,one should use componentDidMount as componentWillMount is deprecated in new version of react.

componentDidMount() {
        axios.get('http://api./abc',
            {
                headers: { "Postman-Token": "abc" }
            })
            .then((response) => { //use arrow to get setState on this call without any extra binding or placeholder variable
                console.log(response.data);
                this.setState({
                    data: response.data,
                })
            })
            .catch((error) => {
                console.log(error)
            })
    }

Try to fix those lines of code:

  constructor(props) { //fixed
    super(props); //fixed
    this.state ={
        data:[],
    }
  }

This is just the way ReactJS set up the constructor() method for a class component . We just obey the React's rules while working with it.

From the Official React Document , they said:

The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.

For more information about the contructor() method: https://reactjs.org/docs/react-component.html#constructor

This is a working example which I've already made just for you as a reference.

The demo is now available on CodeSandBox: https://codesandbox.io/s/8xvn8yl1l2

TitleBar.js

 import React, { Component } from 'react'; import axios from 'axios'; export default class TitleBar extends Component { constructor(props) { super(props); this.state = { data: [] }; } componentDidMount() { axios .get('https://jsonplaceholder.typicode.com/posts') .then(res => { console.log(res.data); this.setState({ data: res.data }); }) .catch(err => console.log(err.message)); } render() { return ( <div> {this.state.data.map(i => ( <div key={i.id}> <h2>{i.title}</h2> </div> ))} </div> ); } } 

App.js

 import React, { Component } from 'react'; import TitleBar from './components/TitleBar'; class App extends Component { render() { return ( <div> <TitleBar></TitleBar> </div> ); } } export default App; 

By following this example, if the this.state.data is still undefine , then there are two things that we could focus on in order to successfully debug:

1.The structure of the response data object. In your case, the solution could be

this.setState({
   data: response.data.DATA  
})

2.Does the API work as expected.

Hopefully that helps.

Your API response object includes an object like:

const response = {
  data: {
    MESSAGE: "List details Fetch successful",
    STATUS: "SUCCESS",
    DATA: [
      { id: 1, name: "foo" },
      { id: 2, name: "bar" },
      { id: 3, name: "baz" }
    ],
    HASH: "3--0"
  }
};

So, you need response.data.DATA for your state here:

this.setState( { data: response.data.DATA } );

Here is a working example of mimicking your situation.

 const remoteData = { data: { MESSAGE: "List details Fetch successful", STATUS: "SUCCESS", DATA: [ { id: 1, name: "foo" }, { id: 2, name: "bar" }, { id: 3, name: "baz" }, ], HASH: "3--0", }, }; const fakeRequest = () => new Promise( resolve => setTimeout( () => resolve( remoteData ), 1000 ) ); class App extends React.Component { state = { data: [], }; componentDidMount() { fakeRequest().then( response => this.setState( { data: response.data.DATA } ) ); } render() { return ( <div> {this.state.data.map( el => ( <div key={el.id}> <p>{el.id}</p> <p>{el.name}</p> </div> ) )} </div> ); } } ReactDOM.render( <App />, document.getElementById( "root" ) ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div> 

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