ReactJS:渲染图像数组
ReactJS: Rendering an array of images
我还是 ReactJS 的新手,我目前正在摆弄 Spotify API,它工作得很好,但我在尝试渲染通过 API。
起初,我尝试在 render()
组件中调用它,但它只生成一个空 'undefined' 图像列表,只显示 alt 属性。其次,我在里面试了一下return()
和前者一样的症状,这次完全没有任何图像。
这个问题只会在我尝试使用 .map()
方法时出现;当我单独渲染图像时,它工作得很好。
import React, { Component } from "react";
let someData = "hello";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
playlists: { name: [], plist_id: [], albumArt: [] }
};
}
getPlaylists(someData) {
let plistNames = [];
let plistContents = [];
let plistArts = [];
someApi
.searchPlaylists(someData)
.then(data => {
if (data.playlists.items) {
if (data.playlists.items.length > 0) {
console.log(data);
data.playlists.items.forEach(plist => {
plistNames.push(plist.name);
plistContents.push(plist.id);
plistArts.push(plist.images[0].url);
this.setState({
playlists: {
name: plistNames,
plist_id: plistContents,
albumArt: plistArts
}
});
});
}
}
})
.catch(err => {
console.error(err);
});
}
render() {
//Produces a list of empty images with only the alt attribute showing up
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist.albumArt} alt="Album Art"/>
})
return (
<div className="App">
<button onClick={() => this.getPlaylists(someData)}>
Get Playlist
</button>
{_playlists}
{/* THIS PRODUCES a similar sympton as the former
{playlists.albumArt.map((plist, index) => {
<img key={index} src={plist.albumArt} alt="Album Art"/>
})
} */}
{/* THIS IMAGE RENDERS THE FIRST ELEMENT FROM THE ARRAY AND WORKS FINE
<img src={playlists.albumArt[0]}/> */}
</div>
);
}
}
如何解决这样的问题?非常感谢您的时间和帮助。
条件内联语句呢?这样它接收到信息后会渲染?
{this.state.playlist.name ?
//have your code here to display
:
<LoadingSpinner />
}
我不能肯定地说,因为我需要查看返回数据的结构,但我相当有信心您不想要在其中设置状态forEach()
循环了很多次。
相反,您可能希望映射数据结果并将其转换为一些有用的对象数组,然后再将其添加到状态,以便您可以在 render
中映射它(看起来不错)并可预测地访问内容。
话虽如此,我希望 searchPlaylists
调用后的 .then()
块看起来更像:
const playlistsWrangled = data.playlists.items.map(plist => ({
name: plist.name,
plist_id: plist.id,
albumArt: plist.images[0].url
}));
this.setState({ playlists: wrangledPlaylists });
我认为你的两种情况的区别在于,在 "working" 一种情况下,你没有 alt 道具。
如果您希望图像在加载过程中清晰显示,则必须走捷径。要么使用为您逐步处理图像加载的模块,要么,如果您不关心可访问性,请将 alt 标签设为空并为图像提供默认背景颜色(如果您愿意,可以在加载后设置 alt 标签)。
您目前正在使用以下方式映射您的专辑封面数组:
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist.albumArt} alt="Album Art"/>
})
问题是您将 <img />
标签的 src
设置为 plist.albumArt
,而实际上“plist”的值是您想要的 url:
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist} alt="Album Art"/>
})
正如其他人提到的,也不建议在循环期间设置状态。而是 loop/map 遍历数据并将其存储在一个局部变量中,您可以使用该变量调用一次 setState。
我还是 ReactJS 的新手,我目前正在摆弄 Spotify API,它工作得很好,但我在尝试渲染通过 API。
起初,我尝试在 render()
组件中调用它,但它只生成一个空 'undefined' 图像列表,只显示 alt 属性。其次,我在里面试了一下return()
和前者一样的症状,这次完全没有任何图像。
这个问题只会在我尝试使用 .map()
方法时出现;当我单独渲染图像时,它工作得很好。
import React, { Component } from "react";
let someData = "hello";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
playlists: { name: [], plist_id: [], albumArt: [] }
};
}
getPlaylists(someData) {
let plistNames = [];
let plistContents = [];
let plistArts = [];
someApi
.searchPlaylists(someData)
.then(data => {
if (data.playlists.items) {
if (data.playlists.items.length > 0) {
console.log(data);
data.playlists.items.forEach(plist => {
plistNames.push(plist.name);
plistContents.push(plist.id);
plistArts.push(plist.images[0].url);
this.setState({
playlists: {
name: plistNames,
plist_id: plistContents,
albumArt: plistArts
}
});
});
}
}
})
.catch(err => {
console.error(err);
});
}
render() {
//Produces a list of empty images with only the alt attribute showing up
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist.albumArt} alt="Album Art"/>
})
return (
<div className="App">
<button onClick={() => this.getPlaylists(someData)}>
Get Playlist
</button>
{_playlists}
{/* THIS PRODUCES a similar sympton as the former
{playlists.albumArt.map((plist, index) => {
<img key={index} src={plist.albumArt} alt="Album Art"/>
})
} */}
{/* THIS IMAGE RENDERS THE FIRST ELEMENT FROM THE ARRAY AND WORKS FINE
<img src={playlists.albumArt[0]}/> */}
</div>
);
}
}
如何解决这样的问题?非常感谢您的时间和帮助。
条件内联语句呢?这样它接收到信息后会渲染?
{this.state.playlist.name ?
//have your code here to display
:
<LoadingSpinner />
}
我不能肯定地说,因为我需要查看返回数据的结构,但我相当有信心您不想要在其中设置状态forEach()
循环了很多次。
相反,您可能希望映射数据结果并将其转换为一些有用的对象数组,然后再将其添加到状态,以便您可以在 render
中映射它(看起来不错)并可预测地访问内容。
话虽如此,我希望 searchPlaylists
调用后的 .then()
块看起来更像:
const playlistsWrangled = data.playlists.items.map(plist => ({
name: plist.name,
plist_id: plist.id,
albumArt: plist.images[0].url
}));
this.setState({ playlists: wrangledPlaylists });
我认为你的两种情况的区别在于,在 "working" 一种情况下,你没有 alt 道具。
如果您希望图像在加载过程中清晰显示,则必须走捷径。要么使用为您逐步处理图像加载的模块,要么,如果您不关心可访问性,请将 alt 标签设为空并为图像提供默认背景颜色(如果您愿意,可以在加载后设置 alt 标签)。
您目前正在使用以下方式映射您的专辑封面数组:
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist.albumArt} alt="Album Art"/>
})
问题是您将 <img />
标签的 src
设置为 plist.albumArt
,而实际上“plist”的值是您想要的 url:
let _playlists = this.state.playlists.albumArt.map((plist, index) => {
return <img key={index} src={plist} alt="Album Art"/>
})
正如其他人提到的,也不建议在循环期间设置状态。而是 loop/map 遍历数据并将其存储在一个局部变量中,您可以使用该变量调用一次 setState。