2
import Request from 'superagent';

const getApi = () => {
    let url = '/* URL */';
    return Request.get(url).then((res) => {
        this.setState({
             content: res.body
        });
    });
}

export default getApi;

I've created function in external file for api call. How do I get access to function/setState in external file?

componentWillMount(){
   getApi();
}

I receive this error:

'TypeError: Cannot read property 'setState' of undefined'

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
René
  • 51
  • 8
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Mayank Shukla Jun 07 '17 at 08:21
  • 1
    pass a `callback method` into `getApi()` method and call that method once you get the response, do setState inside that callback method. – Mayank Shukla Jun 07 '17 at 08:22
  • 1
    You can't, you need to return the response and then setState in the function – Shubham Khatri Jun 07 '17 at 08:22
  • You should read [How does the “this” keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Thomas Jun 07 '17 at 08:32

3 Answers3

4

You can pass in a callback to the getApi function from your component.

const getApi = (onSuccess) => {
    let url = '/* URL */';
    return Request.get(url).then((res) => {
        onSuccess(res.body);
    });
}

Component

componentWillMount(){
   getApi(this.setApiResponse);
}

setApiResponse(data) {
    this.setState({
        content: data
    });
}

NB. As your project grows larger, you may wish to look into a state management system, such as Redux.

Tom
  • 2,321
  • 2
  • 18
  • 29
1

Technically you could pass the instance to getApi so that it knows what this is supposed to be. But imo. that's a poor approach. It creates unnecessary dependencies. At the moment, getApi() needs to know how the React class works; the function is responsible to manipulate the state of the Instance correctly.

Better if getApi() only returns the value, and the instance consumes it:

const getApi = () => {
    let url = '/* URL */';
    return Request.get(url).then(res => res.body);
}

componentWillMount(){
   getApi().then(content => this.setState({ content }));
}
Thomas
  • 11,958
  • 1
  • 14
  • 23
1

My Solution:

function getApi(component) {
        let url = '/* url */';
        return Request.get(url).then((res) => {
            component.setState({
                content: res.body,
            });
        });
    }

componentWillMount(){
   getApi(this);
}
René
  • 51
  • 8