user10248088
user10248088

Reputation: 75

In react, how to update state after doing a fetch?

I have a state which is an empty array:

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

I need to fill up that state with the following data that get when I do a GET request:

See image

See image

UPDATED:

export function copyTestScenarioLog(tSL) {
    console.log("\nCalled copyTestScenarioLog");
    let url = config.base_url + `/test_scenario_logs`;
    return fetch(url, {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + getUserToken() },
        body: JSON.stringify({
            _id: tSL._id['$oid']
        })
    })
    .then(res => res.json())
    .then(data => { 
        getTestStepLogs(data)
        return data;
    })
    .catch(err => console.log(err));
}

export function getTestStepLogs(data) {
    const id = data.test_step_logs[0].$oid;
    let url = config.base_url + `/test_step_logs/${id}`;
    return fetch(url, {
        method: 'GET',
        headers: { 'Authorization': 'Bearer ' + getUserToken() }
    })
    .then(res => res.json())
    .then(data => {
        console.log(data)
        return data 
    })
    .catch(err => console.log(err));
}

How do I update my state after doing a GET fetch?

Upvotes: 3

Views: 1312

Answers (4)

adred
adred

Reputation: 43

For an async call, there are three states. Call initiation, call success and call failure. Say "isLoading" represents the status of the call being running in the background.

Initially => { isLoading : false, data : '', err : '' }

Call initiated => { isLoading : true, data : '', err: '' }

Call success => { isLoading : false, data : response.data err: '' }

Call failed => { isLoading :false, data : '', err: err }

Usually, the GET calls of a component are made in componentDidMount. It is also the suggested way as per the react documentation.

componentDidMount(){
  //Call Initiation
  this.setState({
    isLoading : true,
    data : '',
    err: ''
  });
  makeApiCall(api).
  then((response) => {
    this.setState({
      isLoading : false,
      data : response.data
      err: ''
    });
  }, 
  (err) => {
    this.setState({
      isLoading :false,
      data : '',
      err: err
    })
  })
  .catch((err) => {
    this.setState({
      isLoading :false,
      data : '',
      err: err
    })
  })
}

Upvotes: 0

Atul
Atul

Reputation: 430

if you are using the get call at multiple place, you can be little generic and try this approach.

//return here does not do anything right now

export function getTestStepLogs(data) {
    return new Promise(function(resolve, reject){
    const id = data.test_step_logs[0].$oid;
    let url = config.base_url + `/test_step_logs/${id}`;
    return fetch(url, {
        method: 'GET',
        headers: { 'Authorization': 'Bearer ' + getUserToken() }
    })
    .then(res => res.json())
    .then(data => {
        console.log(data)
        resolve(data);
    })
    .catch(err => {console.log(err);
            reject(err);
        });
  })

}

async componentDidMount() {
    let data = await copyTestScenarioLog();

  //now set it to state
}

Upvotes: 0

Phoenix
Phoenix

Reputation: 4284

you can pass onSuccess function into your getTestStepLogs and update your state.

export function getTestStepLogs(data , onSuccess) {
    const id = data.test_step_logs[0].$oid;
    let url = config.base_url + `/test_step_logs/${id}`;
    return fetch(url, {
        method: 'GET',
        headers: { 'Authorization': 'Bearer ' + getUserToken() }
     }).then(resp => {
     if (onSuccess)
        onSuccess(resp);

}).catch(err => console.log(err));
}  

and when you call getStepLogs pass onSuccess as props:

this.props.getTestStepLogs(data , (resp)=>{
 this.setState({test_steps:resp});
})

Upvotes: 1

jsDevia
jsDevia

Reputation: 1292

This is full react component code, you see how I call your funciton in componentDidMount, and in here I pass 'this' as an argument to copyTestScenarioLog.

import React, { Component } from 'react';
import copyTestScenarioLog from './copyTestScenarioLog';

class Component1 extends Component {
    constructor(props) {
        super(props);
        this.state = {
            test_steps: []
        };
    }

    componentDidMount() {
        var reactComponent = this;
        copyTestScenarioLog('i dont konw that is tsl', reactComponent);
    }

    render() {
        return (
            <div></div>
        );
    }
}

export default Component1;

In 'copyTestScenarioLog', I get that ( refers to react component), and use setState function in react.

export function copyTestScenarioLog(tSL, reactComponent) {
    console.log("\nCalled copyTestScenarioLog");
    let url = config.base_url + `/test_scenario_logs`;
    return fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + getUserToken() },
        body: JSON.stringify({
            _id: tSL._id['$oid']
        })
    })
        .then(res => res.json())
        .then(data => {
            getTestStepLogs(data)
            reactComponent.setState({
                test_steps: data
            });
            return data;
        })
        .catch(err => console.log(err));
}

But basically I don't use this approach, I just wanted to show that how its done, I usually use await/async or function generators, because they are better approaches. Search about them and learn to use them.

Upvotes: 2

Related Questions