Я впервые пользуюсь этим сайтом, так что потерпите меня... Я пытаюсь отобразить массив из 10 видео YouTube из списка воспроизведения, используя API YouTube. Пока я могу console.info данные json из API. Хотя проблема возникает, когда я пытаюсь отобразить эти данные json в своем приложении для реагирования, используя функцию карты.
Вот весь мой код:
import React, { Component } from "react";
import './Videos.css';
import VideosCP from '../Pages/VideosPage/VideosSearch'
import youtubeSearch from "../../api/youtubeSearchApi";
import VideosList from "../Pages/VideosPage/VideoList";
const YOUTUBE_PLAYLIST_ITEMS_API = 'https://www.googleapis.com/youtube/v3/playlistItems';
let url = `${YOUTUBE_PLAYLIST_ITEMS_API}?part=snippet&playlistId=myPlaylistId&maxResults=10&key=myYoutubekey`
function Demo() {
}
class Videos extends Component{
state = {
videoMetaInfo:[],
selectedVideoId: null
}
onVideoSelected = videoId => {
this.setState({
selectedVideoId:videoId
})
}
onSearch = async keyword => {
const response = await youtubeSearch.get("/search",{
params:{
q:keyword
}
})
console.info(this.state);
this.setState({
videoMetaInfo: response.data.items,
selectedVideoId: 'Nl3DoewG3Co'
})
}
playlistRender = async () => {
const data = await fetch(url);
let commits = await data.json();
console.info('data', commits)
}
render(){
const Data = ({data}) => {
data = this.playlistRender()
const results = data.items.map((item)=>{
const {id, snippet = {}} = item
const title = snippet
return(
<li key = {id}>
<h3>{title}</h3>
</li>
)
});
return results
}
return(
<div className = "wrapper">
<div className = "wrapper-inner scroll">
<VideosCP onSearch = {this.onSearch}/>
<VideosList onVideoSelected = {this.onVideoSelected}
data = {this.state.videoMetaInfo}/>
<ul>
<Data/>
</ul>
</div>
</div>
);
}
}
export default Videos
Код отлично компилируется в терминале, но в браузере выдает ошибку: «Не удается прочитать карту свойств неопределенного».
Следовательно, ошибка вызвана этой строкой, в которой говорится: data.items.map((item)=>{
Что еще более странно, так это то, что консоль в браузере распознает, что в массиве есть «элементы». Почему браузер выдает мне эту ошибку? Может ли он не отображать элементы? Если да, то почему бы и нет? И как эта ошибка лечится?
Я пробовал все до сих пор, и это самое близкое, что я получил, но пока нет результатов.
Пожалуйста, помогите мне, переполнение стека - моя единственная надежда...
Я очень отчаялся и попытался исправить различные глупости. Но до этого момента я получаю TypeError: this.state.commits.map не является функцией
сделайте небольшой перерыв, когда чувствуете стресс или отчаяние. :) После перерыва сначала проверьте URL-адрес вашего API, если он правильный, попробуйте его с почтальоном, чтобы проверить, возвращает ли он данные. Возможно, ваш вызов API не вернул данные или выдал ошибку. Потому что у вас нет блока обработчика исключений.
Но мой API возвращает данные imgur.com/a/pFvHW9x idk, если это считается :/
Проблема решена :)
Рад за тебя. :) Но опять же, чтение жизненных циклов компонентов React и механизма состояния будет полезно для вас. И, конечно же, дать перерыв. :)
Данные, которые вы загружаете из API, имеют состояние, поэтому вам нужно установить их в состояние после загрузки. Затем вы можете сопоставить эту информацию о состоянии, как только она появится.
Я также добавил вызов метода componentDidMount
, чтобы убедиться, что мы вызываем API после монтирования компонента.
class Videos extends Component{
state = {
videoMetaInfo:[],
selectedVideoId: null,
commits: []
}
onVideoSelected = videoId => {
this.setState({
selectedVideoId:videoId
})
}
onSearch = async keyword => {
const response = await youtubeSearch.get("/search",{
params:{
q:keyword
}
})
console.info(this.state);
this.setState({
videoMetaInfo: response.data.items,
selectedVideoId: 'Nl3DoewG3Co'
})
}
playlistRender = async () => {
const data = await fetch(url);
let commits = await data.json();
this.setState({ commits });
}
componentDidMount() {
this.playlistRender();
}
render(){
return(
<div className = "wrapper">
<div className = "wrapper-inner scroll">
<VideosCP onSearch = {this.onSearch}/>
<VideosList onVideoSelected = {this.onVideoSelected}
data = {this.state.videoMetaInfo}/>
<ul>
{this.state.commits.map((item) => {
const {id, snippet = {}} = item
const title = snippet
return (
<li key = {id}>
<h3>{title}</h3>
</li>
)
})}
</ul>
</div>
</div>
);
}
}
export default Videos
+1, вы можете удалить destructuring
в своем компоненте Data
, ничего не передается как prop
или, если что-то будет передано, this.playListRender()
перезаписывает это, что возвращает Promise<undefined>
. Поэтому я считаю, что вы можете удалить весь компонент Data
из render
, поскольку в вашем примере есть реализация no
.
Приветствую вас здесь, я попробовал ваше исправление, но оно просто заканчивается "TypeError: this.state.commits.map is not a function"... Спасибо, хотя
Я предположил, что все, что возвращается из вызова API, является массивом, но если это не так, вам придется выяснить, как преобразовать его в нужный вам формат.
Это странная часть, API возвращает действительный массив, в котором я пытаюсь сопоставить «элементы» из этого массива... но мой код отказывается сопоставлять его:/ Я чувствую, что приближаюсь к исправлению.
И вы определенно инициализируете состояние commits
пустым массивом?
Вот что выдает мне консоль imgur.com/QcJQQVm судя по скриншоту, предметы точно есть, так что я знаю, что они существуют.
Так что, возможно, это должно быть { commits: commits.items }
или, возможно, { commits: commits.data.items }
Я предполагаю, что это новое предложение будет состоять в том, чтобы добавить его в commits.items
или commits.data.items
, где находится строка this.setState({ commits });
. Я попробовал оба и вот что я получил: commits.items
дает мне Objects are not valid as a React child (found: object with keys {publishedAt, channelId, title, description, thumbnails, channelTitle, playlistId, position, resourceId}). If you meant to render a collection of children, use an array instead
и commits.data.items
дает мне: Unhandled Rejection (TypeError): Cannot read property 'items' of undefined
Ах-ха, мы приближаемся! Так что это почти наверняка commits.items
. Теперь он жалуется, потому что title
— это не строка, а объект. Таким образом, вы, вероятно, захотите изменить const title = snippet
на const { title } = snippet
, так как snippet
, похоже, имеет множество различных свойств.
Хьюстон, мы взлетели! imgur.com/a/4AfokWO
есть так много вещей, которые я не понимаю: ваш метод "playlistrender" не возвращает никаких данных, но вы пытаетесь присвоить переменную данных в своем компоненте данных в методе render(). Зачем определять аргумент данных для вашего компонента данных. И самое главное, вы можете ожидать рендеринга, если ваши данные находятся в состоянии вашего компонента. В противном случае вам необходимо принудительно обновить компонент. Вам следует прочитать несколько статей о жизненных циклах компонентов состояния и класса.