Uncaught TypeError: this.state.map не является функцией - PullRequest
0 голосов
/ 09 июля 2019

В React я использую Axios для сопоставления массива и вывода списка названий фильмов, которые извлекаются из API MovieDB.Он прекрасно подключается к MovieDB, однако я получаю следующую ошибку в консоли:

Uncaught TypeError: this.state.movies.map не является функцией

Я считаю, что это препятствует выводу списка фильмов в браузер.

Ссылка Codesandbox здесь .

Вот компонент SearchBar, в котором лежит код:

    import React, { Component } from "react";
    import TextField from "@material-ui/core/TextField";
    import axios from "axios";

    import "../SearchBar/_search-bar.scss";

    class SearchBar extends Component {
      state = {
        userSearchTerm: "",
        movies: []
      };

      // When user types, match the value to state
      onInputChange = e => {
        this.setState({ userSearchTerm: e.target.value });
      };

      // On submitting the input, grab the API
      onInputSubmit = e => {
        e.preventDefault();

        const movieName = this.state.userSearchTerm;
        const KEY = "XXXXXXXXXX";

        const searchQuery = `https://api.themoviedb.org/3/search/movie?api_key=${KEY}&language=en-US&query=${movieName}&page=10`;

        axios.get(searchQuery).then(res => {
          this.setState({ movies: res.data });
        });
      };

      render() {
        return (
          <div>
            <form onSubmit={this.onInputSubmit}>
              <TextField
                label="Search for a movie and hit enter..."
                margin="normal"
                className="search-bar"
                onChange={this.onInputChange}
              />
            </form>
            <ul>
              {this.state.movies.map(movie => (
                <li key={movie.id}>{movie.results.title}</li>
              ))}
            </ul>
          </div>
        );
      }
    }

    export default SearchBar;

Кстати, я протестировал этот же код, но с другим API, и он работал просто отлично.Что-то не так с самим API или this.state.movies.map?

Ответы [ 3 ]

3 голосов
/ 09 июля 2019

Рабочий код:

import React, { Component } from "react";
import TextField from "@material-ui/core/TextField";
import axios from "axios";

import "../SearchBar/_search-bar.scss";

class SearchBar extends Component {
  state = {
    userSearchTerm: "",
    movies: []
  };

  // When user types, match the value to state
  onInputChange = e => {
    this.setState({ userSearchTerm: e.target.value });
  };

  // On submitting the input, grab the API
  onInputSubmit = e => {
    e.preventDefault();

    const movieName = this.state.userSearchTerm;
    const KEY = "XXXXXX";

    const searchQuery = 'https://api.themoviedb.org/3/search/movie?api_key=${KEY}&language=en-US&query=${movieName}&page=10';

    axios.get(searchQuery).then(res => {
      console.log("res is ------", res)
      this.setState({ movies: res.data.results });
    });
  };

  render() {
    return (
      <div>
        <form onSubmit={this.onInputSubmit}>
          <TextField
            label="Search for a movie and hit enter..."
            margin="normal"
            className="search-bar"
            onChange={this.onInputChange}
          />
        </form>
        <ul>
          {this.state.movies.map(movie => (
            <li key={movie.id}>{movie.original_title}</li>
          ))}
        </ul>
      </div>
    );
  }
}

export default SearchBar;

Вы должны использовать this.setState({ movies: res.data.results }); и <li key={movie.id}>{movie.original_title}</li>

Дайте мне знать, если это работает.

2 голосов
/ 09 июля 2019

Используемый вами API возвращает объект с «результатами», являющимися ключом, который вы ищете. Если вы обновите свой setState до this.setState({ movies: res.data.results });, вы получите то, что ищете.

Схема ответа Axios

В качестве примечания я бы охранял вашу функцию карты с помощью чего-то вроде {Array.isArray(this.state.movies) && this.state.movies.map(movie => (..., что будет условно отображать выходные данные только тогда, когда movies установлен в состояние и является массивом.

0 голосов
/ 09 июля 2019

You need to change the setState call to this:
this.setState({ movies: res.data.results });

The response is not an array, it is an object like this:

{
  "page": 10,
  "total_results": 136643,
  "total_pages": 6833,
  "results": [
    {
      "vote_count": 110,
      "id": 13189,
      "video": false,
      "vote_average": 7.3,
      "title": "A Christmas Carol",
      "popularity": 6.52,
      "poster_path": "/m3T3iLdE6J5PrqvvP0XNHBvM2bm.jpg",
      "original_language": "en",
      "original_title": "A Christmas Carol",
      "genre_ids": [
        18,
        10751,
        14,
        10770
      ],
      "backdrop_path": "/gaTpxTYQMGoagtMVYK8F7SjqTGM.jpg",
      "adult": false,
      "overview": "An old bitter miser who makes excuses for his uncaring nature learns real compassion when three ghosts visit him on Christmas Eve.",
      "release_date": "1984-12-17"
    },
    {
      "vote_count": 419,
      "id": 12103,
      "video": false,
      "vote_average": 6.1,
      "title": "Don't Say a Word",
      "popularity": 9.995,
      "poster_path": "/qx3hgW9MqxsEEFjx4eSbpp1Fe2l.jpg",
      "original_language": "en",
      "original_title": "Don't Say a Word",
      "genre_ids": [
        53
      ],
      "backdrop_path": "/AaOtoMzqWJPSNXPRKwbvqf6MbKo.jpg",
      "adult": false,
      "overview": "When the daughter of a psychiatrist is kidnapped, he's horrified to discover that the abductors' demand is that he break through to a post traumatic stress disorder suffering young woman who knows a secret..",
      "release_date": "2001-09-28"
    }
  ]
}
...