最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ReactFetchAPI: How to take data from related json by id - Stack Overflow

programmeradmin5浏览0评论

I want to take data from JSON, next take another data from related JSON by ID and push it to my state array movies.

This is my code:

state = {
    movies: []
}

ponentDidMount() {

    fetch(';page=1')
        .then(response => response.json())
        .then(data => {
            const movies = data.results;

            movies.forEach(movie => this.moviePageAndGenres(movie.id, movie));

            this.setState({
                movies
            });
        })
}

moviePageAndGenres = (id, element) => {
    fetch('/' + id + '?api_key=APIKEY')
        .then(response => response.json())
        .then(data => {
            element.genres = data.genres;
            element.homepage = data.homepage;
        });
}

In render() I just console.log my movies to check if data inside is correct.

Output: image

So it's correct but when I check Component Props these props are not transferred.

image

This is how I transfer props:

const movies = this.state.movies.map(movie =>
 <Movie genres={movie.genres}
        homepage={movie.homepage}
        key={movie.id}
        title={movie.title}
        poster={movie.poster_path}
        rating={movie.vote_average}
 />
)

I guess it's problem with multiple call of asynchronousfetch(). But i don't know how to handle with it.

I want to take data from JSON, next take another data from related JSON by ID and push it to my state array movies.

This is my code:

state = {
    movies: []
}

ponentDidMount() {

    fetch('https://api.themoviedb/3/movie/popular?api_key=APIKEY&page=1')
        .then(response => response.json())
        .then(data => {
            const movies = data.results;

            movies.forEach(movie => this.moviePageAndGenres(movie.id, movie));

            this.setState({
                movies
            });
        })
}

moviePageAndGenres = (id, element) => {
    fetch('https://api.themoviedb/3/movie/' + id + '?api_key=APIKEY')
        .then(response => response.json())
        .then(data => {
            element.genres = data.genres;
            element.homepage = data.homepage;
        });
}

In render() I just console.log my movies to check if data inside is correct.

Output: image

So it's correct but when I check Component Props these props are not transferred.

image

This is how I transfer props:

const movies = this.state.movies.map(movie =>
 <Movie genres={movie.genres}
        homepage={movie.homepage}
        key={movie.id}
        title={movie.title}
        poster={movie.poster_path}
        rating={movie.vote_average}
 />
)

I guess it's problem with multiple call of asynchronousfetch(). But i don't know how to handle with it.

Share Improve this question edited Jan 19, 2019 at 16:25 zyng9 asked Jan 19, 2019 at 16:10 zyng9zyng9 771 gold badge2 silver badges10 bronze badges 3
  • please hide your api key – sdkcy Commented Jan 19, 2019 at 16:14
  • this.setState will not wait for your moviePageAndGenres to respond. – Manish Jangir Commented Jan 19, 2019 at 16:16
  • you can try to use async functions – Pommesloch Commented Jan 19, 2019 at 16:24
Add a ment  | 

2 Answers 2

Reset to default 2

The reason its not working is, you are firing multiple fetch calls which are async and setting the state immediately after it. setState will get empty movies in that case.

fetch api returns a promise and you should set your state in promise resolution handler. Modify your ponentDidMount like this.

ponentDidMount() {

  fetch('https://api.themoviedb/3/movie/popular?api_key=APIKEY&page=1')
      .then(response => response.json())
      .then(data => {
          const movies = data.results;
          Promise.all(movies.map(movie => fetch(
            `https://api.themoviedb/3/movie/${movie.id}?api_key=APIKEY`
          )))
          .then(resp => Promise.all( resp.map(r => r.json()) ))
          .then(result => {
            const movies = result.map((data, i) => {
              const movie = Object.assign(movies[i], {
                genres: data.genres,
                homepage: data.homepage
              });
              return movie;
            });
            this.setState({
              movies
            });
          });
      })
}

You need async await in this case and it’s good to use Promise.all because you are doing fetch in forEach.

For forEach you need await Promise.all and for fetch you need await. Which mean it will wait until the forEach is pleted

Change

    fetch('https://api.themoviedb/3/movie/popular?api_key=APIKEY&page=1')
    .then(response => response.json())
    .then(data => {
        const movies = data.results;

        movies.forEach(movie => this.moviePageAndGenres(movie.id, movie));

        this.setState({
            movies
        });
    })

To

  fetch('https://api.themoviedb/3/movie/popular?api_key=APIKEY&page=1')
    .then(response => response.json())
    .then(async data => {
        const movies = data.results;
        await Promise.all(movies.forEach(async movie => await this.moviePageAndGenres(movie.id, movie)))

        this.setState({
            movies
        });
    })

Also

Change

  moviePageAndGenres = (id, element) => {
      fetch('https://api.themoviedb/3/movie/' + id + '?api_key=APIKEY')
    .then(response => response.json())
    .then(data => {
        element.genres = data.genres;
        element.homepage = data.homepage;
    });
 }

To

   moviePageAndGenres = async (id, element) => {
      return await fetch('https://api.themoviedb/3/movie/' + id + '?api_key=APIKEY')
    .then(response => response.json())
    .then(data => {
        element.genres = data.genres;
        element.homepage = data.homepage;
    });
 }
发布评论

评论列表(0)

  1. 暂无评论