Shakhor
Shakhor

Reputation: 250

Fetch return undefined in react

I'm trying to use WordPress API with react, but it returns id instead of the tag name, so I'm trying to fetch the tag name with another API call. but it keeps returning undefined. When I add return before fetch inside getCategory() it just errors out.

componentDidMount() {
const URL =
  'https://public-api.wordpress.com/wp/v2/sites/sitename/posts/';

  fetch(URL)
  .then(res => res.json())
  .then(posts => {

    const post = posts.map(post => {
      return {
        ...post,
        categories: this.getCategory(...post.categories)
      };
    });

    this.setState({ posts: post });

    console.log(post);
  })
  .catch(err => console.log(err));
  }

  getCategory(id) {
   const URL = `https://public-api.wordpress.com/wp/v2/sites/sitename/categories/${id}`;

fetch(URL)
  .then(data => data.json())
  .then(res => res.name)
 }

Upvotes: 0

Views: 8214

Answers (3)

ersin.erdal
ersin.erdal

Reputation: 41

first: getCategory method returns nothing.

getCategory(id) {
   const URL = `https://public-api.wordpress.com/wp/v2/sites/sitename/categories/${id}`;

return fetch(URL).then(data => data.json()).then(res => res.name);

}

second: when you run setState method (probably) http request for category (getCategory) is still running, so categories are not set yet.

you should use Promise.all() method to be sure all http requests are done before you call setState method.

Upvotes: 1

ionizer
ionizer

Reputation: 1721

Referencing @lyosha-korogoda's answer, if you can't use async/await, try something like this instead:

componentDidMount() {
  const URL = 'https://public-api.wordpress.com/wp/v2/sites/<YOUR_WORDPRESS_URL>/posts/';

  fetch(URL)
    .then(res => res.json())
    .then(posts => {
      this.getCategory(...post.categories).then(category => {
        const post = posts.map(post => {
          return {
            ...post,
            categories: category
          };
        });
        this.setState({ posts: post });
        console.log(post);
      })
    })
    .catch(err => console.log(err));
}

getCategory(id) {
  const URL = `https://public-api.wordpress.com/wp/v2/sites/<YOUR_WORDPRESS_URL>/categories/${id}`;

  return fetch(URL)
    .then(data => data.json())
    .then(res => res.name)
}

Note how I moved getCategory out and wrapping the map into it's then block. Honestly the code could be cleaner, but just to show how it works.

As to why your fetch returns undefined, first it's because your getCategory(id) did not return anything. And second, it's simply because how JavaScript's asynchronous nature really, so your const post doesn't have value because getCategory(id) has not finished at that time.

Upvotes: 0

user9539019
user9539019

Reputation:

Basically, your problem is that you're setting the state before the fetch in getCategory resolves. To address that, you can await for its result --

componentDidMount() {
  const URL = 'https://public-api.wordpress.com/wp/v2/sites/sitename/posts/';  
  fetch(URL)
    .then(res => res.json())
    .then(posts => {
      return Promise.all(posts.map(async post => {
        return {
          ...post,
          categories: await this.getCategory(...post.categories)
        };
      }));
    })
    .then(posts => this.setState({ posts: posts }))
    .catch(err => console.log(err));
}

getCategory(id) {
  const URL = `https://public-api.wordpress.com/wp/v2/sites/sitenameress.com/categories/${id}`;

  return fetch(URL)
    .then(data => data.json())
    .then(res => res.name)
} 

Upvotes: 2

Related Questions