【问题标题】:React Material UI ListItem ClickReact Material UI ListItem 点击
【发布时间】:2020-08-28 15:32:31
【问题描述】:

我想创建一个国家列表,其中的 ListItems 是可点击的,并且每个 ListItem 在点击时在文本附近都有一个图标。我创建了一个列表,并实现了列表的可点击属性。但是,当我单击列表中的一个列表项时,我无法在 1 次单击中选择另一个项目,它首先取消选择前一个,然后选择另一个。这是我的实现包含的部分代码:

class CountryList extends Component {
  constructor(props) {
    super(props);
    this.state = {clicked: false};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      clicked: !state.clicked
    }));
  }

  render() {
    const {classes} = this.props;
    const { clicked } = this.state;

    let listItems = myList.map((item) =>
      <>
        <ListItem className={ clicked ? classes.listItemClicked : classes.listItemNotClicked }
          onClick={this.handleClick} classes={classes.ListItem} button key={item.id}>
        
            {clicked ? 
            <ListItemIcon><DoneIcon style={{ color: 'rgb(239, 239, 239)', fontSize: '2.2rem' }}/></ListItemIcon>
           : <ListItemIcon><DoneIcon style={{ display: 'none', color: 'rgb(239, 239, 239)', fontSize: '2.2rem', backgroundColor: 'rgb(239, 239, 239)' }}/></ListItemIcon>}

           <ListItemText classes={{primary: classes.listItemText}} primary={item.value} />
       </ListItem>
       <Divider /> 
      </>
    );

    return (
      <List className={classes.list}>{listItems}</List>
    );
  }
}


const myList = [
  {id: 1, value: 'Albania'}, {id: 2, value: 'Austria'}, {id: 3, value: 'Belarus'}, {id: 4, value: 'Belgium'}, 
  {id: 5, value: 'Bosnia'}, {id: 6, value: 'Bulgaria'}, {id: 7, value: 'Croatia'}, {id: 8, value: 'Cyprus'}, 
  {id: 9, value: 'Czech'}, {id: 10, value: 'Denmark'}, {id: 11, value: 'Estonia'}, {id: 12, value: 'Finland'}, 
  {id: 13, value: 'France'}, {id: 14, value: 'Germany'}, {id: 15, value: 'Greece'}, {id: 16, value: 'Hungary'}, 
  {id: 17, value: 'Iceland'}, {id: 18, value: 'Ireland'}, {id: 19, value: 'Italy'}, {id: 20, value: 'Latvia'}, 
  {id: 21, value: 'Lithuania'}, {id: 22, value: 'Luxembourg'}, {id: 23, value: 'Macedonia'}, 
  {id: 24, value: 'Malta'}, {id: 25, value: 'Moldova'}, {id: 26, value: 'Montenegro'}, 
  {id: 27, value: 'Netherlands'}, {id: 28, value: 'Norway'}, {id: 29, value: 'Pakistan'}, 
  {id: 30, value: 'Poland'}, {id: 31, value: 'Portugal'}, {id: 32, value: 'Romania'}, {id: 33, value: 'Russia'}, 
  {id: 34, value: 'Serbia'}, {id: 35, value: 'Slovakia'}, {id: 36, value: 'Slovenia'}, 
  {id: 37, value: 'Spain'}, {id: 38, value: 'Sweden'}, {id: 39, value: 'Switzerland'}, {id: 40, value: 'Turkey'}, 
  {id: 41, value: 'Ukraine'}, {id: 42, value: 'Others'}
];

这是 App.js 文件中的代码:

<CountryList myList={myList} />

另外,我在文本前添加了一个图标。当我单击 1 个项目时,它会显示图标,但是如果我的鼠标在它上面,它还会显示另一个元素图标。我想显示单击元素的图标。我怎样才能做到这一点?

这是截图:

如果你仔细看,比利时旁边有一个图标。

这是codesandbox中代码的链接:https://codesandbox.io/s/gifted-snow-5p1gd?file=/src/Country.js

【问题讨论】:

  • 您应该创建一个最小的可重现示例(最好在 codesandbox 上)

标签: javascript reactjs material-ui


【解决方案1】:

这是一个有效的demo

您需要保持活动列表项处于状态,正如我在您的代码中看到的 this.state.clicked 是一个布尔值,所以现在您无法设置单击元素的样式,因为没有被选中的引用

设置状态以保留被点击的项目

this.state = { clickedItem: "" };

将 onClick 更改为。

<ListItem
    key={item.id}
    className={
      this.state.clickedItem === item.id
        ? classes.listItemClicked
        : classes.listItemNotClicked
    }
    onClick={() => this.handleClick(item)}
>

在 onCLick 中设置被点击的项为状态

handleClick(item) {
  this.setState({
    clickedItem: item.id
  });
}

现在您已将点击的项目置于状态,在下一次渲染中(由于上述状态更改将发生)您可以在渲染中具有以下逻辑

<ListItem
  key={item.id}
  className={
    this.state.clickedItem === item.id //if item.id === clickedItemId then add a separate css class
      ? classes.listItemClicked
      : classes.listItemNotClicked
  }
  onClick={() => this.handleClick(item)}
>
  <ListItemIcon>
    //if item.id === clickedItemId then show the DoneIcon
    {this.state.clickedItem === item.id && (
      <DoneIcon
        style={{ color: "rgb(239, 239, 239)", fontSize: "2.2rem" }}
      />
    )}
  </ListItemIcon>
  <ListItemText primary={item.value} />
</ListItem>

【讨论】:

  • 感谢您的回复。我错过了handleClick方法的参数。您的解决方案按我的意愿工作。有趣的是,代码中的一个小细节改变了很多结果!
【解决方案2】:

您必须使用索引映射点击。试试这个:

class CountryList extends Component {
  constructor(props) {
    super(props);
    this.state = {clicked: null};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(key) {
    this.setState(state => ({
      clicked: key
    }));
  }

  render() {
    const {classes} = this.props;
    const { clicked } = this.state;

    let listItems = myList.map((item, index) =>
      <>
        <ListItem className={ clicked == index ? classes.listItemClicked : classes.listItemNotClicked }
          onClick={this.handleClick} classes={classes.ListItem} button key={item.id}>
        
            {clicked == index ? 
            <ListItemIcon><DoneIcon style={{ color: 'rgb(239, 239, 239)', fontSize: '2.2rem' }}/></ListItemIcon>
           : <ListItemIcon><DoneIcon style={{ display: 'none', color: 'rgb(239, 239, 239)', fontSize: '2.2rem', backgroundColor: 'rgb(239, 239, 239)' }}/></ListItemIcon>}

           <ListItemText classes={{primary: classes.listItemText}} primary={item.value} />
       </ListItem>
       <Divider /> 
      </>
    );

    return (
      <List className={classes.list}>{listItems}</List>
    );
  }
}


const myList = [
  {id: 1, value: 'Albania'}, {id: 2, value: 'Austria'}, {id: 3, value: 'Belarus'}, {id: 4, value: 'Belgium'}, 
  {id: 5, value: 'Bosnia'}, {id: 6, value: 'Bulgaria'}, {id: 7, value: 'Croatia'}, {id: 8, value: 'Cyprus'}, 
  {id: 9, value: 'Czech'}, {id: 10, value: 'Denmark'}, {id: 11, value: 'Estonia'}, {id: 12, value: 'Finland'}, 
  {id: 13, value: 'France'}, {id: 14, value: 'Germany'}, {id: 15, value: 'Greece'}, {id: 16, value: 'Hungary'}, 
  {id: 17, value: 'Iceland'}, {id: 18, value: 'Ireland'}, {id: 19, value: 'Italy'}, {id: 20, value: 'Latvia'}, 
  {id: 21, value: 'Lithuania'}, {id: 22, value: 'Luxembourg'}, {id: 23, value: 'Macedonia'}, 
  {id: 24, value: 'Malta'}, {id: 25, value: 'Moldova'}, {id: 26, value: 'Montenegro'}, 
  {id: 27, value: 'Netherlands'}, {id: 28, value: 'Norway'}, {id: 29, value: 'Pakistan'}, 
  {id: 30, value: 'Poland'}, {id: 31, value: 'Portugal'}, {id: 32, value: 'Romania'}, {id: 33, value: 'Russia'}, 
  {id: 34, value: 'Serbia'}, {id: 35, value: 'Slovakia'}, {id: 36, value: 'Slovenia'}, 
  {id: 37, value: 'Spain'}, {id: 38, value: 'Sweden'}, {id: 39, value: 'Switzerland'}, {id: 40, value: 'Turkey'}, 
  {id: 41, value: 'Ukraine'}, {id: 42, value: 'Others'}
];

【讨论】:

  • 感谢您的回复。运行代码时,即使我选择了一个元素,它的颜色也不会改变。我认为代码中有一个缺失。我会尝试编辑您的代码。
猜你喜欢
  • 2015-07-05
  • 2021-01-08
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 2019-08-19
  • 2017-07-27
相关资源
最近更新 更多