简体   繁体   English

React JS onClick设置点击索引的状态

[英]React JS onClick set state of clicked index

How can I update isSelected to true for the item that the user clicks on? 我如何将用户单击的项目的isSelected更新为true?

Here is my handleSelect function so far: 到目前为止,这是我的handleSelect函数:

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. 该功能通过props正确传递,并且正在运行,我遇到的问题是逻辑。

The current logic sets all items in the array to true which is incorrect. 当前逻辑将数组中的所有项目设置为true,这是不正确的。 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,
      }
    ]
  }

Here's how we can do it: 我们的方法如下:

  1. On each clicked Genre, we get its id . 在每个点击的流派上,我们都获得其id
  2. After we have the id , then we toggle the selected genre isSelected flag. 拥有id ,然后切换选定的流派isSelected标志。
  3. Please follow updateGenres method, to check how we did it in an immutable way. 请遵循updateGenres方法,以检查我们是如何完成的。
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. 这种方法的好处是您不必依赖allGenresindex ,并且切换实现将与演示文稿分离。 Imagine if you change the genres sort (from ASC to DESC), then you have to change your toggle logic too. 想象一下,如果您更改了流派排序(从ASC到DESC),那么您也必须更改切换逻辑。

Easiest way is that maintain allGenres and selectedGenre separately in state 最简单的方法是分别维护allGenresselectedGenrestate
So handleSelect will be like 所以handleSelect就像

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

If the i passed to handleSelect is the index of the genre in the genres array then 如果传递给handleSelectigenres数组中流派的索引,则

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 如果i指的是流派的id ,则

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 components being rendered, and that you want to click in these components... You could use bind and pass to the callback function the index of the array... for example: 我假设您正在渲染一些组件,并且想要单击这些组件...您可以使用bind并将数组的索引传递给回调函数...例如:

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. 我在li的onClick回调中使用bind ,因此可以访问您的回调中的体裁索引。

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. 但是,还有其他一些方法可以执行此操作,因为您具有该类型的ID,因此您可能希望使用该ID来代替索引,但是这取决于您自己决定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM