最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React JS onClick set state of clicked index - Stack Overflow

programmeradmin0浏览0评论

How can I update isSelected to true for the item that the user clicks on?

Here is my handleSelect function so far:

handleSelect(i) {
  //Get Genres
  let genres = this.state.allGenres;
  genres = genres.map((val, index) => {
    //val.isSelected = index === true;
    return val;
  }); 
  //Set State
  this.setState({
    allGenres: genres
  })
}

This function is passed down correctly via props and is working, the issue I'm having is with the logic.

The current logic sets all items in the array to true which is incorrect. I only want to update / toggle the state of the item the user clicked.

I have an array of objects within state, here is what one of the objects looks like:

state = {
    allGenres: [
      {
        id: 1,
        genreTitle: 'Horror',
        isSelected: false,
      }
    ]
  }

How can I update isSelected to true for the item that the user clicks on?

Here is my handleSelect function so far:

handleSelect(i) {
  //Get Genres
  let genres = this.state.allGenres;
  genres = genres.map((val, index) => {
    //val.isSelected = index === true;
    return val;
  }); 
  //Set State
  this.setState({
    allGenres: genres
  })
}

This function is passed down correctly via props and is working, the issue I'm having is with the logic.

The current logic sets all items in the array to true which is incorrect. I only want to update / toggle the state of the item the user clicked.

I have an array of objects within state, here is what one of the objects looks like:

state = {
    allGenres: [
      {
        id: 1,
        genreTitle: 'Horror',
        isSelected: false,
      }
    ]
  }
Share Improve this question asked Jun 1, 2018 at 10:25 FilthFilth 3,22815 gold badges55 silver badges83 bronze badges 1
  • the i passed to handleSelect refers to what ? The index in the genres array or the id of the genre, or something else ? – Gabriele Petrioli Commented Jun 1, 2018 at 10:57
Add a ment  | 

4 Answers 4

Reset to default 2

Here's how we can do it:

  1. On each clicked Genre, we get its id.
  2. After we have the id, then we toggle the selected genre isSelected flag.
  3. Please follow updateGenres method, to check how we did it in an immutable way.
updateGenres(selectedId) {
   const { allGenres } = this.state

   this.setState({
     // Here we make sure we don't mutate the state
     allGenres: allGenres.map(genre => ({
        ...genre,
        // Toggle the clicked one, and reset all others to be `false`.
        isSelected: genre.id === selectedId
        // If you want to keep the values of the rest genres, then the check should be: 
        // isSelected: (genre.id === selectedId) ? !genre.isSelected : genre.isSelected
     }))
   })
}

renderGenres() {
  const { allGenres } = this.state

  return allGenres.map(genre => <Gengre onClick={() => this.updateGenres(genre.id) })
}

render() {
  return <div>{this.renderGenres()}</div>
}

The benefit of this approach is that you don't depend on the index of the allGenres and your toggle implementation will be decoupled to the presentation. Imagine if you change the genres sort (from ASC to DESC), then you have to change your toggle logic too.

Easiest way is that maintain allGenres and selectedGenre separately in state
So handleSelect will be like

handleSelect(id) {
  this.setState({
    selectedGenre: id
  });
}

If the i passed to handleSelect is the index of the genre in the genres array then

handleSelect(i) {
  //Get Genres
  let genres = this.state.allGenres;
  genres = genres.map((val, index) => {
    val.isSelected = index === i;
    return val;
  }); 

  //Set State
  this.setState({
    allGenres: genres
  })
}

if the i refers to the id of the genre then

handleSelect(i) {
  //Get Genres
  let genres = this.state.allGenres;
  genres = genres.map((val) => {
    val.isSelected = val.id === i;
    return val;
  }); 
  //Set State
  this.setState({
    allGenres: genres
  })
}

I'll assume that you have some ponents being rendered, and that you want to click in these ponents... You could use bind and pass to the callback function the index of the array... for example:

class Component extends React.Component {
  constructor() {
    super();

    this.state = {
      allGenres: [{
        id: 1,
        genreTitle: 'Horror',
        isSelected: false
      }]
    }
  }

  handleSelect(i) {
    //Get Genres
    let genres = this.state.allGenres;
      genres = genres.map((val, index) => {
      val.isSelected = index === i;
      return val;
    });
    //Set State
    this.setState({
      allGenres: genres
    })
  }

  render() {
    const {allGenres} = this.state;

    return (
      <ul>
        :D
        {allGenres.map((genre, i) => (
          <li onClick={this.handleSelect.bind(this, i)}>
            {genre.genreTitle} {genre.isSelected && 'Is Selected'}
          </li>
        ))}
      </ul>
    );
  }
}

I'm using bind in the onClick callback from the li, this way I have access to the genre index in your callback.

There are some other ways of doing this though, since you have the id of the genre, you might want to use that instead of the index, but it's up to you to decided.

发布评论

评论列表(0)

  1. 暂无评论