Доступ к свойствам объекта

#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} указать, что вы загружаете данные.)

У вас есть два варианта. Либо:

  1. Учтите тот факт, что у вас может еще не быть данных при рендеринге, или
  2. Не извлекайте данные в этом компоненте; вместо этого извлеките их в родительском компоненте и не отображайте этот компонент, пока у вас не будут данные (которые вы передадите в качестве реквизита).