Реакция: Как исправить 'Uncaught TypeError: this.state.data.map не является функцией' - PullRequest
0 голосов
/ 02 июня 2019

Я получаю сообщение об ошибке «Uncaught TypeError: this.state.data.map не является функцией», даже если я могу успешно записать данные на консоль из API. Я нашел похожие вопросы, но пока не нашел хорошего решения, чтобы решить эту проблему.

Я прочитал здесь , что "Объекты {} в JavaScript не имеют метода .map (), это только для массивов, []." Однако я не могу понять, как решить эту проблему, выполнить итерацию по объекту и получить данные для внешнего интерфейса React. Спасибо и любая помощь будет принята с благодарностью.

import React, { Component } from "react";
import axios from "axios";

export default class GetSubjects extends Component {
  constructor(props) {
    super(props);
    this.getsubjects = this.getsubjects.bind(this);
    this.onSearch = this.onSearch.bind(this);
    this.state = {
      keyword: "",
      data: []
    };
  }
  getsubjects(e) {
    this.setState({ keyword: e.target.value });
  }
  onSearch(e) {
    e.preventDefault();
    const searchsub = {
      keyword: this.state.keyword
    };
    axios
      .get(`http://localhost:3000/api/messages/courses/${this.state.keyword}`)
      .then(response => {
        console.log(response);
        this.setState({
          data: response.data
        });
      });
    console.log(this.state.keyword);
    console.log(this.state.data);
  }
  componentDidMount() {}

  render() {
    return (
      <div>
        <br />
        <div>
          <label>Course Name</label>{" "}
          <input
            placeholder="Enter Course Name"
            type="text"
            value={this.state.keyword}
            onChange={this.getsubjects}
            name="keyword"
            required
          />{" "}
          <button className="btn btn-primary" onClick={this.onSearch}>
            Get Subjects
          </button>
        </div>
        <br />
        <table className="table table-bordered">
          <thead>
            <tr>
              <th scope="col">Course Name</th>
              <th scope="col">Subjects</th>
            </tr>
          </thead>
          <tbody>
            {this.state.data.map(function(subject) {
              return (
                <tr>
                  {" "}
                  <td key={subject.id}>{subject.name}</td>{" "}
                  <td key={subject.id}>{subject.subjects}</td>{" "}
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    );
  }
}

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

Вы сказали, что вы получаете:

{
    "subjects": ["Computer Architecture", "Basic Networking"],
    "_id": "5cf368bfb58f8c35bc19cebc",
    "name": "Software Engineering",
    "passmark": 75,
    "lectureIncharge": "John Smith",
    "__v": 0
}

Ваш setState вызов устанавливает data для этого объекта, который не является массивом.

Ваш код render ожидает, что это будет массив. Он пытается перебрать его и использовать для заполнения строк в таблице. Но вы получаете только один фрагмент данных: один курс ("Software Engineering"), который охватывает два предмета ("Computer Architecture" и "Basic Networking").

Так что ваш код render не должен пытаться использовать его как массив (и поэтому вам больше не понадобится таблица). Он должен просто использовать data name и subjects свойства напрямую.

Я пока оставлю разметку вашей таблицы, но учтите, что при этом получается только одна строка (потому что есть только один фрагмент данных). До return я бы взял курс:

const course = this.state.data;

то, куда вы выводите свою таблицу:

<tbody>
  {course && course.name
  ? undefined
  :
  <tr>
    <td key={course.id}>{course.name}</td>{" "}
    <td key={course.id}>{course.subjects.join(", ")}</td>{" "}
  </tr>
  }
</tbody>

Я использовал явное join(", "), чтобы присоединиться к темам, а не неявным образом через toString, который не будет содержать пробел после запятой.

0 голосов
/ 02 июня 2019

response.data - это объект, который axios заполняет, когда запрос выполнен.Это правда, что вы инициализируете data как массив, но когда вы делаете: this.setState({ data: response.data }); Вы фактически изменили его на объект.

Анализируете объект, который вы получаете, в массиве или делаете что-то еще свозвращенные данные.

Редактировать : После ответа: просто выполните: this.setState({data: response.data.subject});

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...