#javascript #reactjs
#javascript #reactjs
Вопрос:
На last.fm Мне нужна ссылка на список самых популярных треков. Появляется ошибка «TypeError: не удается прочитать свойство ‘track’ неопределенного». Как я могу получить доступ к свойству «name»?
import React, {Component} from 'react';
export default class App extends Component {
state={
data: [],
}
async componentDidMount() {
const response = await
fetch(`http://ws.audioscrobbler.com/2.0/?method=tag.gettoptracksamp;tag=discoamp;api_key=f21dfa58ed2c6c4a65227b8f730c281bamp;format=json`,
)
const data = await response.json();
this.setState({
data: data,
})
}
render() {
const{data} = this.state
console.log (data.tracks.track.name)//TypeError: Cannot read property 'track' of undefined
return (
<div>
</div>
)
}
}
Комментарии:
1.
track
это также массив, к которому вы не можете получить доступtrack.name
Ответ №1:
Изначально data
это пустой массив. Пытайтесь получить доступ к вложенным данным только после получения ответа и заполнения массива. Используя хуки, вы могли бы сделать что-то вроде следующего:
const App = () => {
const [tracks, setTracks] = React.useState();
React.useEffect(() => {
fetch(`http://ws.audioscrobbler.com/2.0/?method=tag.gettoptracksamp;tag=discoamp;api_key=f21dfa58ed2c6c4a65227b8f730c281bamp;format=json`)
.then(res => res.json())
.then((result) => {
setTracks(result.tracks);
});
//.catch(handleErrors);
}, []);
if (tracks) {
console.log(tracks.track[0].name);
}
return (
<div>
</div>
)
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>
Ответ №2:
При первом рендеринге (по крайней мере) вашим состоянием будет только то состояние, которое вы установили в своем конструкторе, поэтому, естественно data.tracks
, не определено. (Обратите также внимание, что ваше начальное состояние имеет data
вид массива, но при этом вы используете его как объект, не являющийся массивом data.tracks
. Я предполагаю, что то, что вы получаете, должно быть объектом, а не массивом. Но я подозреваю data.tracks
, что это массив, поэтому вы, вероятно, захотите data.tracks[x].name
, где x
находится индекс, и вы, вероятно, захотите инициализировать состояние {data: {tracks: []}}
или {data: null}
указать, что вы загружаете данные.)
У вас есть два варианта. Либо:
- Учтите тот факт, что у вас может еще не быть данных при рендеринге, или
- Не извлекайте данные в этом компоненте; вместо этого извлеките их в родительском компоненте и не отображайте этот компонент, пока у вас не будут данные (которые вы передадите в качестве реквизита).