React - toggle css类

时间:2017-05-14 06:22:43

标签: javascript reactjs react-dom

我希望能够在列表的单个项目上打开/关闭“活动”类。假设我们有一个元素列表:

<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>

我希望能够在点击时在第二个元素上添加类“active”。我不能使用state,因为它会改变其他2个元素的类,如果我们在那里添加条件,对吧?

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

有没有人有更简单的解决方案?

没有必要使用另一个大的npm模块,document.getElementsByClassName(显然)也不是refs,这将是非常好的。

2 个答案:

答案 0 :(得分:2)

解决这个问题的正确方法是使用一个状态变量来定义哪一个当前是“活动的”,即

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设置为当前所选元素的索引/ ref是一件简单的事情。

答案 1 :(得分:2)

您可以在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>