ReactJs - я не могу поймать переменную вне цикла axios

У меня есть база данных JSON и компонент React, которые извлекают эти данные. Вот моя БД JSON:

{
  "houses": [
    {
      "id": 1,
      "name": "house 1"       
    },
    {
      "id": 2,
      "name": "house 2"        
    },
    {
      "id": 3,
      "name": "house 3"
     }       
  ]
}

Он извлекается компонентом ReactJS. Когда я делаю console.info() внутри цикла Axios, он работает успешно. Но внутри метода рендеринга он не работает. Как я могу это решить?

class Houses extends Component {
  constructor(props) {
    super(props);
    this.state = {
      index:0,         
      currentHouse:[]      
    };      
  }

  componentDidMount() { 
    axios.get(URL_HOUSES)
      .then(res => {        
        this.setState({ index:0 })
        this.setState({ currentHouse: res.data})          
        //Here is working! It is returning the index and the current house's name      
        console.info('index:' + this.state.index)             
        console.info(
                     'Name of the current house:' +  
                      this.state.currentHouse[this.state.index].name
                    ) 
    }

  render() {                  

    return (
      <div>     
        //Here isn't working. It is returning an error message:  
        //TypeError: Cannot read property '0' of undefined

        <h3>{this.state.currentHouse[this.state.index].name}</h3>
      </div>
    );
  }
}   


export default Houses
Поведение ключевого слова "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) для оценки ваших знаний,...
2
0
230
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Причина этой ошибки в том, что метод render() пытается отобразить данные до того, как эти данные станут доступны. Попробуйте следующее, чтобы решить эту проблему:

class Houses extends Component {
  constructor(props) {
    super(props);
    this.state = {
      index:0,         
      currentHouse:[]      
    };      
  }

  componentDidMount() { 
    axios.get(URL_HOUSES)
      .then(res => {        
        /* Combine into single setState call (this is optional, but 
           makes for cleaner code. Note that calling setState will
           trigger the component to render() again, which will cause
           your currentHouse[0].name to be rendered into <h3> below  */
        this.setState({ index:0, currentHouse: res.data })
    }

  render() {                  

    /* Detect if currentHouse data is ready/avalible - if not, render
       a temporary loading message */
    if (this.state.currentHouse.length === 0) {
       return <p>Loading</p>
    } 

    /* If we reach this point, then there is data in this.state.currentHouse
       that can be accessed and rendered */
    return (
      <div>         
        <h3>{this.state.currentHouse[this.state.index].name}</h3>
      </div>
    );
  }
}   


export default Houses
Ответ принят как подходящий

TL;DR проверьте исходный массив currentHouse перед его отображением в методе рендеринга.

При первоначальном рендеринге вашего компонента в массиве currentHouse нет элементов.

Итак, когда ваш компонент пытается распечатать ваше выражение this.state.currentHouse[this.state.index].name, на самом деле он пытается найти 0-ю позицию пустого массива []. Это будет оцениваться какundefined.

Вариант исправить это — установить начальное значение для массива currentHouse в состоянии или проверить, есть ли значения в массиве. Например:

 <h3>{this.state.currentHouse.length && this.state.currentHouse[this.state.index].name}</h3>

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