React.JS组件的onClick函数,如何更具体的结果

时间:2018-05-07 11:17:53

标签: javascript reactjs jsx

目前我有一个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;

提前致谢!

4 个答案:

答案 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 />}