目前我有一个React组件,它从API中获取音乐艺术家的数据,并创建一个媒体对象列表,显示其详细信息。媒体对象具有onClick功能,因此当单击一个框时,它会显示一个具有更多特定细节的子组件,这些都可以正常工作,
然而,当单击列表中的一个对象时,它们将显示它们下面的子组件。我该如何缩小范围,以便可以单独点击列表中的每个对象而不影响其他对象?
这是我的代码:
import React, { Component } from 'react';
import axios from 'axios';
import ArtistChild from './track-child';
class ArtistListEntry extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isHidden: true,
artist: []
};
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
componentDidMount() {
this.ArtistListEntry();
}
ArtistListEntry() {
axios.get('https://api-v2.hearthis.at/feed/?type=popular&page=1&count=20')
.then(
({ data }) => {
this.setState({
artist: data
})
})
.catch((error) => {
if (error.response) {
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
console.log(error.config);
});
}
render() {
let artists = this.state.artist.map((item) => (
<div>
<div className='media media-top' key={ item.user.id } onClick={this.toggleHidden.bind(this)}>
<div className='media-left media-middle'>
<img src={ item.user.avatar_url } className='media-object artist-image' />
</div>
<div className='media-body'>
<ul className='artist-info-list'>
<li className='media-heading'>{ item.user.username }</li>
<li className='media-genre'>{ item.genre }</li>
<a className='media-release' href={ item.permalink_url }>Visit Artist Page</a>
</ul>
</div>
</div>
{!this.state.isHidden && <ArtistChild />}
</div>
));
return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">
{ artists }
</div>
</div>
);
}
}
export default ArtistListEntry;
提前致谢!
答案 0 :(得分:2)
您正在维护单个状态以切换所有列表项相同的视图,因此您需要维护隐藏项目的列表,或者更好的方法是存储需要显示的项目(如果只有一个)需要立即显示)
import React, { Component } from 'react';
import axios from 'axios';
import ArtistChild from './track-child';
class ArtistListEntry extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isVisible: '',
artist: []
};
}
toggleHidden (id) {
this.setState({
isVisible: id
})
}
componentDidMount() {
this.ArtistListEntry();
}
ArtistListEntry() {
axios.get('https://api-v2.hearthis.at/feed/?type=popular&page=1&count=20')
.then(
({ data }) => {
this.setState({
artist: data
})
})
.catch((error) => {
if (error.response) {
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
console.log(error.config);
});
}
render() {
let artists = this.state.artist.map((item) => (
<div>
<div className='media media-top' key={ item.user.id } onClick={this.toggleHidden.bind(this, item.id)}>
<div className='media-left media-middle'>
<img src={ item.user.avatar_url } className='media-object artist-image' />
</div>
<div className='media-body'>
<ul className='artist-info-list'>
<li className='media-heading'>{ item.user.username }</li>
<li className='media-genre'>{ item.genre }</li>
<a className='media-release' href={ item.permalink_url }>Visit Artist Page</a>
</ul>
</div>
</div>
{this.state.isVisible === item.id && <ArtistChild />}
</div>
));
return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">
{ artists }
</div>
</div>
);
}
}
export default ArtistListEntry;
如果需要切换多个项目,则需要保持所有项目的打开状态
import React, { Component } from 'react';
import axios from 'axios';
import ArtistChild from './track-child';
class ArtistListEntry extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isHidden: {},
artist: []
};
}
toggleHidden (itemId) {
this.setState(prevState => ({
isHidden: {[itemId]: prevState.isHidden[itemId] ? !prevState.isHidden[itemId] : false
}))
}
componentDidMount() {
this.ArtistListEntry();
}
ArtistListEntry() {
axios.get('https://api-v2.hearthis.at/feed/?type=popular&page=1&count=20')
.then(
({ data }) => {
this.setState({
artist: data
})
})
.catch((error) => {
if (error.response) {
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
console.log(error.config);
});
}
render() {
let artists = this.state.artist.map((item) => (
<div>
<div className='media media-top' key={ item.user.id } onClick={this.toggleHidden.bind(this)}>
<div className='media-left media-middle'>
<img src={ item.user.avatar_url } className='media-object artist-image' />
</div>
<div className='media-body'>
<ul className='artist-info-list'>
<li className='media-heading'>{ item.user.username }</li>
<li className='media-genre'>{ item.genre }</li>
<a className='media-release' href={ item.permalink_url }>Visit Artist Page</a>
</ul>
</div>
</div>
{!this.state.isHidden[item.id] && <ArtistChild />}
</div>
));
return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">
{ artists }
</div>
</div>
);
}
}
export default ArtistListEntry;
答案 1 :(得分:1)
问题是你有一个状态属性isHidden
控制所有艺术家的可见性,而不是每个艺术家的状态属性,或者更好的是,activeArtistId
状态属性应该说明哪个艺术家显示。
应该看起来像:
// ...
class ArtistListEntry extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
activeArtistId: null,
artist: []
};
}
toggleHidden (artistId) {
this.setState({
activeArtistId: artistId
})
}
// ...
ArtistListEntry() {
axios.get('...')
.then(
({ data }) => {
this.setState({
artist: data,
activeArtistId: null
})
})
// ...
}
render() {
let artists = this.state.artist.map((item) => (
<div>
<div className='media media-top' key={ item.user.id } onClick={this.toggleHidden.bind(this, item.user.id)}>
{/*...*/}
</div>
{this.state.activeArtistId === item.user.id &&
<ArtistChild artistId={item.user.id} />}
</div>
));
// ...
}
}
答案 2 :(得分:0)
更新你的onClick以获取隐藏对象的id,你的州也会这样做:
this.state = {
error: null,
hidden: {},
artist: []
};
然后你的onClick就是这样:
onClick={() => {
this.setState(prevState => {
return { hidden: { ...prevState, [item.user.id]: !prevState.hidden[item.user.id] } };
});
}}
然后,您将检查state.hidden [item.user.id]是否为真
答案 3 :(得分:0)
您的代码看起来像
toggleHidden (item) {
item.isHidden = (!item.isHidden) || true;
this.forceUpdate();
}
渲染代码
let artists = this.state.artist.map((item) => (
<div>
<div className='media media-top' key={ item.user.id } onClick={this.toggleHidden.bind(this, item)}>
<div className='media-left media-middle'>
<img src={ item.user.avatar_url } className='media-object artist-image' />
</div>
<div className='media-body'>
<ul className='artist-info-list'>
<li className='media-heading'>{ item.user.username }</li>
<li className='media-genre'>{ item.genre }</li>
<a className='media-release' href={ item.permalink_url }>Visit Artist Page</a>
</ul>
</div>
</div>
{item.isHidden && <ArtistChild />}
</div>
));
// you need to check {item.isHidden && <ArtistChild />}