NuzzeSicK
NuzzeSicK

Reputation: 707

How to define a data variable in Vue using API's

I'm doing a little project for showing movies from an API (TMDb) using Vue Routers. So I have a component called 'MovieList' where I connect to the API.
This is my data:

data() {
  return {
    movies: []
  }
}

These are my methods:

methods: {
  getMovies: () => new Promise((resolve, reject)=> {
    const url = `https://api.themoviedb.org/3/discover/movie?api_key=MyAPI`;
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText).results);
      } else {
        reject(Error(xhr.statusText));
      }
    }
    xhr.send();
  })
}

and my mounted:

mounted() {
  this.getMovies().then(
    result => get(result)
  )
  function get(result) {
    result.forEach((el) =>  {
      this.movies = el
    })
  }
}

So, what I want is that the obtained array equals the variable 'movies' declared in 'data'.
Here is a screenshot: enter image description here

And this is the error I get in console:

MovieList.vue?ea6b:34 Uncaught (in promise) TypeError: Cannot set property 'movies' of undefined
    at eval (MovieList.vue?ea6b:36)
    at Array.forEach (<anonymous>)
    at get (MovieList.vue?ea6b:35)
    at eval (MovieList.vue?ea6b:30)

Thanks everyone, hope you can help me!

Upvotes: 0

Views: 51

Answers (2)

Phil
Phil

Reputation: 164811

The code in your mounted hook is a bit strange.

If you want to assign the result to your movies array, all you really need is

export default {
  data: () => ({ movies: [] }),

  // use the "created" hook as it executes earlier
  // and there's no obvious reason to wait longer
  async created () {
    // directly assign the result array to "movies"
    this.movies = await this.getMovies()
  },


  methods: {
    // you don't need to change "getMovies" 
    // but we've come a long way since XMLHttpRequest
    async getMovies () {
      const res = await fetch('https://api.themoviedb.org/3/discover/movie?api_key=MyAPI')
      if (!res.ok) {
        throw res
      }
      return (await res.json()).results
    }
  }
}

Your issue was that inside your get function, this does not refer to the Vue instance.

You also appeared to be trying to overwrite movies with each result in the array which would end up with you only storing the last one.

Upvotes: 1

XuWang
XuWang

Reputation: 359

I don't know what data type API returns, but you can try this

mounted() {
    let _this = this
    _this.getMovies().then(result => {
        _this.movies = result
    })
}

Upvotes: 1

Related Questions