javascriptajaxreactjsreact-starter-kit

Ajax call in React Starter Kit


I'm using React Starter Kit to create my first React app, and I'm struggling with Ajax calls. I saw that this Kit embeds a way to perform Ajax calls (which is by the way used internally for app routing):

import fetch from '../../core/fetch';

I've added this in my component, and then try to perform an Ajax call when the component loads. Here is my code:

  componentDidMount() {

      var moduleManager = 'https://my_domain.com/my_endpoint';

      async function getModules (url) {
          const response = await fetch(url);
          const content = await response.json();
          return content;
      };

      this.state.modulesList = getModules(moduleManager);

      console.log(this.state.modulesList);
  }

I'm also using the state value in my render function:

  render() {
    var rows = [];
    for (var i = 0; i < this.state.modulesList.length; i++) {
        rows.push(
            <li>{this.state.modulesList[i]}<li/>
        );
    }

This code put together logs this in my console:

Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

Then the Ajax call is performed (successfully) and my console is now showing this:

Promise
__proto__:Promise
[[PromiseStatus]]:"resolved"
[[PromiseValue]]:Array[16]

The desired behaviour is of course to update my view: when the ajax calls is performed, display one line per array member.

What am I missing?

Thanks


Solution

  • What I suggest doing:

    constructor() {
      ...
      // Bind your async function to your stateful component's class
      this.getModules = this.getModules.bind(this);
    }
    
    async getModules(url) {
      try {
        // Perform the ajax call
        const response = await fetch(url);
    
        // Convert respone to json
        const content = await response.json();
    
        // Process your content (if needed)
        ...
    
        // Call setState() here
        this.setState({someContent: content});
    
      } catch(e) {
        console.error(e);
      }
    }
    
    componentDidMount() {
      this.getModules(`${URL}`);
    }
    

    You can't actually return the fetched/parsed data from an async function. According to this MDN link, async function returns a promise, and not the actual data you'd expect to get after parsing it.

    What happened in your case, was that you were actually trying to receive a returned value from an async function, inside a regular(sync) function (componentDidMount). You can either do what I suggested, or use .then() to use setState after resolving and parsing the promise, in the actual componentDidMount function.

    I suggest reading about async functions and Promise before continuing.

    Best of luck!