Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

correct way to call api using react

I have a react code as below which basically creates a treemap:

class ChartModal extends Component{
   constructor(props){
      super(props)
}
callApi(){

  fetch(someurl)
  .then((result) => {

    return result.json();
  }).then((jsonResult) => {
    console.log(jsonResult);
  })
}
render(){
  return(
    <Modal
            onOk={() => this.props.toggleVisibility()}
            onCancel={() => this.props.toggleVisibility()}
            visible={this.props.isVisible}
            okText={'ok'}
            cancelText={'cancel'}
            confirmLoading={false}
            title="Intent distribution chart"
        >
            <h1>HOWDY</h1>
            <TreeMap
                data =  {this.callApi()}//this is where i want the data returned by apicall
                width={400}
                valueUnit={'count'}
            />
        </Modal>
    )
  }
}

Now I want the data returned by api call to be used inside the tree map component, but the way I am doing it now doesn't seem to be working. When I run this, the data in the tree map comes out to be null though I expect a json returned by api call to be there.

like image 932
Srijan Sharma Avatar asked Oct 27 '25 03:10

Srijan Sharma


2 Answers

You need to invoke the API in componentWillMount or any other life cycle hooks and in your API callback use setState to ensure that the result is set to the components state variable. That way after the setState your component can access the value resolved by your API call.

NOTE: this.state.result will be null during the first render. Make sure to have a null check in the TreeMap component before accessing this.props.data.

IMP NOTE

Great suggestion from @aram90 about the setState invocation on unmounted components. To avoid this this.canSetState, instance variable is defined by me and added to prevent any possible setState invocation on unmounted components.

I used this approach just to call the API as early as possible even if it means a nanosecond. However, another approach would be to call the API in componentDidMount and then check for this._ismounted instance variable accordingly. For more on this checkout the answer here Is there a way to check if the react component is unmounted?. React docs suggests not to use isMounted().

There are many ways to achieve this but this is more React kind of way.

class ChartModal extends Component{
  constructor(props){
    super(props)

    this.state = {
      result: null
    }
    this.canSetState = false;
  }

  componentWillMount() {
    this.canSetState = true;
    this.callApi();
  }

  componentWillUnmount() {
    this.canSetState = false;
  }

  callApi(){

    fetch(someurl)
    .then((result) => {

      return result.json();
    }).then((jsonResult) => {
      this.canSetState && this.setState({result: jsonResult})
    })
  }

  render(){
    return (
      <Modal
        onOk={() => this.props.toggleVisibility()}
        onCancel={() => this.props.toggleVisibility()}
        visible={this.props.isVisible}
        okText={'ok'}
        cancelText={'cancel'}
        confirmLoading={false}
        title="Intent distribution chart"
      >
        <h1>HOWDY</h1>
        <TreeMap
          data={this.state.result}
          width={400}
          valueUnit={'count'}
        />
      </Modal>
    )
  }
}
like image 193
Nandu Kalidindi Avatar answered Oct 28 '25 16:10

Nandu Kalidindi


The problem is that callApi isn't returning anything. If it's supposed to assign the data somewhere, it isn't. And if does return something, it will be a promise since it's async.

What you can do is use a state variable and map it to the data prop of your TreeMap. Then use the componentDidMount lifecycle function to fetch the data once the component is rendered. Once it responds, update the mapped state variable with the results. In theory, it should re-render TreeMap automatically.

like image 26
Joseph Avatar answered Oct 28 '25 17:10

Joseph