Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with nested fetch request in React

New to React, I'm currently trying to create a data table with data from an API. I want to have a first fetch, and then run another with response from the first (id) in order to complete my table.

Here is my code :

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

        this.state = {
            user: {},
            data: []
        };
    }

    componentDidMount() {
        this.setState({
            user: JSON.parse(localStorage.getItem('user'))
        }, function () {
            this.loadAllObjectsInfo()
        });
    }

    // Fetch all object info in order to fill the table
    loadAllObjectsInfo() {
        const requestOptions = {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'bbuser': this.state.user.userId,
                'bbtoken': this.state.user.secret
            },
        };

        fetch('https://xxxxx/api/objects', requestOptions)
            .then(response => response.json())
            .then((data) => {
                this.setState({ data: data })
            })

    }

With this code, I have the data I want to render my table but I need to run another fetch to get other info with the id coming from the first request.

How can I do that nested fetch request ?

Thanks a lot,

Matthieu

like image 648
JourdanM Avatar asked Dec 10 '22 02:12

JourdanM


2 Answers

You can easily manage this with async/await:

async loadAllObjectsInfo() {
    const requestOptions = {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'bbuser': this.state.user.user
            'bbtoken': this.state.user.secret
        },
    };

    let response = await fetch('https://xxxxx/api/objects', requestOptions);
    let data = await response.json();

    // here is another fetch - change to fit your request parameters (this is just example)
    let info = await fetch('https://xxxxx/api/objects/' + data.id);

    this.setState({ data });
}

You can read more about async function.

like image 198
zhuber Avatar answered Dec 17 '22 07:12

zhuber


@JourdanM, you should return a new fetch request from one of the then handlers. I've made a simple snippet for you. There are no data validators and spinners. This is a simple showcase. =)

A fetch request returns a promise, and you can chain promises by simply returning them from the then handlers. Here is a good article about it, it has great examples: https://javascript.info/promise-chaining

function fetchUser (user) {
  return fetch(`https://api.github.com/users/${user.login}`)
}

class User extends React.Component {
  state = {
    user: null
  }

  componentDidMount () {
    fetch("https://api.github.com/users")
      .then(response => response.json())
      .then(users => fetchUser(users[0]))
      .then(response => response.json())
      .then(user => {
        this.setState({user})
      })
  }
  
  render () {
    return (
      <div>
        <pre>{JSON.stringify(this.state.user, null, 2)}</pre>
      </div>
    )
  }
}

ReactDOM.render(<User />, document.querySelector("#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>
like image 40
Ivan Burnaev Avatar answered Dec 17 '22 05:12

Ivan Burnaev