How to do fetch in react?

All we need is an easy explanation of the problem, so here it is.

Good afternoon, I get json from the server, I process it, but the call to render occurs 2 times.Google, make an empty object in the constructor.And if the object has no property, then undefined is returned, but I also have arrays, from which the application crashes.I attach the code. How to get the data out of the state? Is it possible to fetch in the render and write?

export default class Forma extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: [] };
  }

  componentWillMount() {
    fetch("http://localhost:3001")
      .then(response => response.json())
      .then(result => this.setState({ data: result }))
      .catch(e => console.log(e));
  }

  render() {
    const { data } = this.state;

    return <h1>{console.log(data.goals[0].gs_id)}</h1>; //падает
  }
}

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Use componentDidMount instead of componentWillMount, it’s deprecated.

And that’s a really good addition in Christopher’s answer to handle async operation.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    };
  }
  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then(response => response.json())
      .then(result =>
        this.setState({
          data: result
        })
      )
      .catch(e => console.log(e));
  }
  render() {
    const { data } = this.state;

    return <h1> {data[0] ? data[0].title : 'Loading'} </h1>;
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Method 2

Use an extra state-value that you can toggle when the data has finished fetching. That will help prevent the attempt of using an object property inside an empty array.

export default class Forma extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      data: []
    };
  }
  componentDidMount() {
    fetch('http://localhost:3001')
      .then(response => response.json())
      .then(result => this.setState({ loading: false, data: result }))
      .catch(e => {
        this.setState({ loading: false })
        console.log(e)
      });
  }

  render() {
    const { loading, data } = this.state;

    if (loading) {
      return <span>Loading</span>;
    }

    if (!data || data.length === 0) {
      return <span>No items found</span>;
    }

    return <h1>{data.goals[0].gs_id}</h1>;
  }
}

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply