У меня есть база данных 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



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Причина этой ошибки в том, что метод 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>