1

I'm currently using functions to predefine all of my axios calls so for example:

export const getClients = () => {
    axios.get("/client/")
        .then(response=>{
            return response;
        })
        .catch(error=>{
            return error;
        });
    };

Now, I want to call this in a class-based component in the componentDidMount like this:

  componentDidMount(){
        this.setState({
            clients: getClients()
        });
  }

I can't seem to figure out why when I try to console.log(this.state.clients) at the end of componentDidMount I'm getting an undefined error. I'm new to React and from what I understand, the then in the function of the axios call should resolve the promise and return the actual response from the API call so when I call getClients(), the clients state should be the response.

What am I doing wrong?

DjangoDev1
  • 232
  • 4
  • 14

2 Answers2

1

Okay there is some stuff that needs to be cleared out here :-

  1. You need to change getClients like so :-
export const getClients = () => {
    return axios.get("/client/")
        .then(response=>{
            return response;
        })
        .catch(error=>{
            return error;
        });
    };

Why ? Because the value that you returned from the callback of then is wrapped inside a Promise implicitly and has to be returned for consumption as you do in a function like function sum(a,b) {return a+b}

  1. componentDidMount will change like so :-
componentDidMount(){
       const fetchClients = async () => {
            const clients = await getClients();
             this.setState({clients});
         }
       fetchClients();    
  }

Why ? If you want to use getClients in a statement fashion instead of .then().then() promise chain, you will first wrap it inside an async function and then call await on getClients() (remember this function returns a Promise) and then set the state inside that async function.

  1. Even if you console.log the clients state after fetchClients() within componentDidMount, you probably won't see the value set because setState works asynchronously. So never rely on the console.log of your state just after setting it.
Lakshya Thakur
  • 8,030
  • 1
  • 12
  • 39
  • Thank you but I'm now getting `Unhandled Rejection (TypeError): Cannot read property 'setState' of undefined`. – DjangoDev1 Feb 16 '21 at 12:56
  • Updated fetchClients from regular function to arrow function. Now try. – Lakshya Thakur Feb 16 '21 at 12:59
  • It now works. Just one more questions, why did it work now with an arrow function and not with a regular one seeing as they were both async? And also, can the `await getClients()` be changed to something with `.then(..)` ? – DjangoDev1 Feb 16 '21 at 13:05
  • 1
    Arrow functions take the "this" value from their lexical outer scope and in outer scope the value of "this" is the Class component instance itself. Regular functions don't work that way. I would encourage you to read more about them. A lot of stuff goes behind the scenes. Yes await getClients() can be changed to getClients().then(res=>setState.....). In that case you don't need that wrapper async function. – Lakshya Thakur Feb 16 '21 at 13:09
1
 componentDidMount(){
       fetchClients();    
  }

  const fetchClients = () => {
    getClients().then( (response)=> {
      // handle success
             this.setState({clients:response});

    });
  };
Hithesh kumar
  • 1,008
  • 9
  • 25