frinux
frinux

Reputation: 2092

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

Upvotes: 0

Views: 232

Answers (2)

Dor Weid
Dor Weid

Reputation: 454

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!

Upvotes: 1

U r s u s
U r s u s

Reputation: 6968

Without testing your code, one problem is that you're incorrectly modifying state directly. That doesn't trigger a render and therefore your view is not updated. Try setState() instead, like so:

<li>{this.setState({modulesList[i]})}<li/>

Upvotes: 0

Related Questions