React / FetchAPI: Как получить данные из связанных json по id - PullRequest
0 голосов
/ 19 января 2019

Я хочу взять данные из JSON, затем взять другие данные из связанного JSON по идентификатору и передать их в мой массив состояний movies.

Это мой код:

state = {
    movies: []
}

componentDidMount() {

    fetch('https://api.themoviedb.org/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.org/3/movie/' + id + '?api_key=APIKEY')
        .then(response => response.json())
        .then(data => {
            element.genres = data.genres;
            element.homepage = data.homepage;
        });
}

В render() Я просто console.log мой movies, чтобы проверить правильность данных внутри.

Вывод: image

Так что это правильно, но когда я проверяю Component Props, эти реквизиты не переносятся.

image

Вот как я передаю реквизиты:

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}
 />
)

Я думаю, это проблема с многократным вызовом асинхронного fetch().Но я не знаю, как справиться с этим.

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Причина, по которой он не работает, заключается в том, что вы запускаете несколько вызовов извлечения, которые являются асинхронными, и устанавливаете состояние сразу после него.setState получит пустые фильмы в этом случае.

fetch api возвращает обещание, и вы должны установить свое состояние в обработчике разрешения обещаний.Измените ваш componentDidMount, как это.

componentDidMount() {

  fetch('https://api.themoviedb.org/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.org/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
            });
          });
      })
}
0 голосов
/ 19 января 2019

В этом случае требуется асинхронное ожидание, и хорошо использовать Promise.all, потому что вы делаете выборку в forEach.

Для forEach вам нужно дождаться Promise.all, а для получения нужно дождаться. Это означает, что он будет ждать, пока forEach будет завершен

Изменение

    fetch('https://api.themoviedb.org/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
        });
    })

К

  fetch('https://api.themoviedb.org/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
        });
    })

Также

Изменение

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

К

   moviePageAndGenres = async (id, element) => {
      return await fetch('https://api.themoviedb.org/3/movie/' + id + '?api_key=APIKEY')
    .then(response => response.json())
    .then(data => {
        element.genres = data.genres;
        element.homepage = data.homepage;
    });
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...