4

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?

1
  • async/await is the good option rather than writing promises. Promises will take you to callback hell. Commented Sep 16, 2019 at 9:09

4 Answers 4

6

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.

Sign up to request clarification or add additional context in comments.

Comments

3

@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>

Comments

2

You can write the code as below.

fetch('https://xxxxx/api/objects', requestOptions)
.then(response => response.json())
.then((res1) => {

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

});

Hope this will work for you!

Comments

2

You can also use axios like below

axios.post(url, data, header).then(res => {
        if(res.status === 200){
             console.log('1st data')
            axios.post(url, data, header)
                .then(response => {
                    if (response.status === 200) {
                        console.log('2nd data')
                    } else {
                        console.log('2nd error')
                    }
                });

        }else{
            console.log('1st error')
        }
    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.