ReactJS - Невозможно распечатать задачи, this.props.todos.map не является функцией

Я новичок в реакции, и я пытаюсь распечатать некоторые данные из запроса GET и распечатать их, но я получаю Uncaught TypeError: this.props.todos.map не является функцией - ошибкой.

Если я изменю this.setState({data: data}) на функцию успеха, я смогу получить данные в своей консоли, но есть ли какой-нибудь быстрый и простой способ исправить это, чтобы распечатать данные?

App.js

import React, { Component } from 'react';

import $ from 'jquery';
import Todos from "./Components/Todos"


class App extends Component {
  constructor(){
    super();
    this.state = {
      todos:[]
    }
  }
  getTodos(){
    $.ajax({
      type: "GET",
      url: 'url',
      dataType:'json',
      headers: {
        Authorization: "Basic " + btoa("username" + ":" + "password")
      },
      cache: false,
      success: function(data){
        this.setState({todos: data}, function(){
          console.info(this.state);
        });
      }.bind(this),
      error: function(xhr, status, err){
        console.info(err);
      }
    });
  }
  componentWillMount(){
    this.getTodos();
  }
  componentDidMount(){
    this.getTodos();
  }

  render() {
    return (
      <div className = "App">
        <Todos todos = {this.state.todos}/>
      </div>
    );
  }
}

export default App;

Todos.js

import React, { Component } from 'react';
import TodoItem from './TodoItem';

class Todos extends Component {
  render() {
    let todoItems;
    if (this.props.todos){

      todoItems = this.props.todos.map(todo => {
        return (
          <TodoItem key = {todo.code} todo = {todo} />
        );
      });
    }
    return (
      <div className = "Todos">
        <h3>Results:</h3>
        {todoItems}
      </div>
    );
  }
}

export default Todos;

TodoItem.js

import React, { Component } from 'react';

class TodoItem extends Component {
  render() {
    return (
      <li className = "Todo">
        <strong>{this.props.todo.code}</strong>
      </li>
    );
  }
}


export default TodoItem;

Фрагмент из журнала консоли:

ReactJS - Невозможно распечатать задачи, this.props.todos.map не является функцией

публиковать журнал консоли, который вы получаете, когда делаете console.info (this.state);

Subin Sebastian 26.03.2018 17:31

Можете ли вы console.info(this.state.todos) внутри App.js

Aaqib 26.03.2018 17:34

@Andy this.props.todos инициализируется пустым массивом в компоненте оболочки. this.state = { todos:[] } нет необходимости в нулевой проверке

Subin Sebastian 26.03.2018 17:40

@ Энди, я сталкивался с этой проблемой много раз до такой степени, что могу заметить ее за много миль

Abslen Char 26.03.2018 17:40

что печатается в журнале консоли внутри обратного вызова успеха? вы уверены, что ваш сервер возвращает массив?

Karim 26.03.2018 17:46

Очевидно, что сервер не возвращает массив, он должен возвращать объект, и поэтому .map не является ошибкой функции.

Subin Sebastian 26.03.2018 17:47

@Subin также может быть неопределенным, когда он пытается отобразить элемент, поэтому карта функций выдает ошибку, поскольку он пытается выполнить рендеринг до того, как состояние будет заполнено ответом

Abslen Char 26.03.2018 17:50

@AbdeslemCharif никогда не будет неопределенным, поскольку он правильно инициализирован в конструкторе компонентов приложения. Начальное состояние - это пустой массив. Первоначально он будет передаваться в пустом массиве, что не вызовет никаких проблем. Затем его сервер может вернуться и возразить, что он передает его, и второй рендеринг Todos выдает эту ошибку.

Subin Sebastian 26.03.2018 17:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
8
216
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Во-первых, бесполезно вызывать this.getTodos() дважды, просто вызовите его в методе componentDidMount(), еще одна вещь, о которой вам нужно знать, компонент TodoItem.js не будет отображать значение this.props.todo.code, чтобы избежать проблемы, которую вам нужно добавить в свой TodoItem.js

class TodoItem extends Component {
  render() {
    if (!this.props.todo){
       <div>Loading</div>
      }
    return (
      <li className = "Todo">
        <strong>{this.props.todo.code}</strong>
      </li>
    );
  }
}

Array.prototype.map() ожидает массив, поэтому, если вы попытаетесь передать ему неопределенное значение, он автоматически выдаст ошибку, если я верю, что это так в вашем приложении

еще одна вещь, сделайте это с this.state.todo, прежде чем пробовать мое решение

Запрошенные данные находятся внутри {}, а не в массиве, поэтому я получаю сообщение об ошибке?

IlariM 26.03.2018 17:43

он также может быть undefined, так как вы пытаетесь выполнить рендеринг до получения ответа, также добавил этот this.getTodos = this.getTodos.bind(this) в свой конструктор

Abslen Char 26.03.2018 17:44

Вам также необходимо привязать функцию getTodos для ссылки на область класса внутри нее. Так что привяжите его внутри конструктора:

this.getTodos = this.getTodos.bind(this)

Это не имеет значения, поскольку this.getTodos вызывается из componentDidMount (), а не передается как onClick или onChange. Также к этому привязаны обратные вызовы внутри getTodos.

Subin Sebastian 26.03.2018 17:45
Ответ принят как подходящий

todos всегда должен быть массивом. Поэтому измените setState вот так в своей функции успеха.

this.setState({todos: (data.resources ? data.resources : [])}, function(){
          console.info(this.state);
        });

Другие вопросы по теме