反应 - 切换 css class

React - toggle css class

我希望能够在列表的单个项目上切换 class "active" on/off。假设我们有一个元素列表:

<ul>
  <li><a href="#" className="list-item">First</a></li>
  <li><a href="#" className="list-item">Second</a></li>
  <li><a href="#" className="list-item">Third</a></li>
</ul>

我希望能够在点击时在第二个元素上添加 class "active"。我不能为此使用状态,因为它会改变其他 2 个元素的 classes,如果我们在那里添加条件,对吗?

所以解决方案可能是创建一个子组件,比如 <ListItem />,它可以有自己的状态和自己的 onclick 方法,这只会改变他自己的 class。但是,当我们想要在点击时删除其他元素上的 class "active" 时,该子组件必须将方法分派给父级以从其他元素中删除 class 。对于一个简单的任务来说似乎相当复杂(你知道 10secs-in-jquery 那种)。

有人对此有更简单的解决方案吗?

如果不必为此使用另一个大的 npm 模块,document.getElementsByClassName(显然)和 refs,那就太好了。

解决此问题的正确方法是使用一个状态变量来定义当前 "active",即

this.state = {
    active: "first" // (or "second", "third", null, etc..) 
};

然后,您可以像这样使用内联 if 语句:

<li><a href="#" className={"list-item" + (this.state.active == "first" ? " active": "")}>First</a></li>

请注意,我假设您要对这些列表元素进行硬编码 - 如果这些元素是动态生成的,只需将 this.state.active 设置为当前所选元素的 index/ref 即可。

您可以在 item 组件外部管理选定状态并将其作为道具传递。
onSelect / onClick 的事件处理程序可以触发和更改 state

const data = [1,2,3,4,5];

class List extends React.Component {
 constructor(props){
   super(props);
      
      this.state = {
       selectedItem: 0
      };
      this.onSelect = this.onSelect.bind(this);
  }
  
  onSelect(id){
   this.setState({
     selectedItem: id
    });
  }
  
  render() {
   const {selectedItem} = this.state;
   return ( 
      <ul>
          {data.map((d, index) => {
           return <ListItem 
                      key={index}
                      selected={index + 1  == selectedItem}
                      value={d}
                      id={d}
                      onSelect={this.onSelect}
                    />
          })}
          
      </ul>
    )
  }
}

const ListItem = (props) => {

  const onSelect = (e) => {
   props.onSelect(e.target.id);
  }
  
  const className = props.selected && "selected";
   
 return <li className={className} id={props.id} onClick={onSelect}>{props.value}</li>
}

ReactDOM.render(<List />, document.getElementById("root"));
ul{
  list-style: none;
}

li{
    padding: 5px;
    border: 1px solid #ccc;
    cursor: pointer;
}

li.selected{
  background-color: green;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>