admin管理员组

文章数量:1417687

I'm struggling with implementing 'toggle class' functionality in React. I have the NavSidebar ponent which is an unordered list ul. My NavListItem ponent is list item li.

When the list item is clicked I need to give the class name active to the clicked li and other list elements should get an empty class name.

Here's what I've e up with by far:

class NavListItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = { active: false };
  }

  setActive(bool) {
    this.setState({ active: bool });
  }

  render() {
    let index = this.props.key;
    let item = this.props.item;
    return (
      <li className={this.state.active ? 'active' : ''}
          onClick={this.setActive(this.props.setActive).bind(this)} >
        <a href={'#'+item}>{item}</a>
      </li>
    );
  }
}

class NavSidebar extends React.Component {

  constructor(props) {
    super(props);
  }

  render () {

    let items = this.props.navItems.map( (item, index) => {
      return (
        <NavListItem key={index} item={item} setActive={true} />
      );
    });

    return (
        <div className="col-sm-2">
          <nav className="nav-sidebar">
            <ul className="nav">
              {items}
              <li className="nav-divider" />
              <li>
                <a href="#"><i className="glyphicon glyphicon-home"></i> Back Home</a>
              </li>
            </ul>
          </nav>
        </div>
    );
  }
}

NavSidebar.propTypes = {
  navItems: React.PropTypes.array
};

Unfortunately, this doesn't work, it never even touches the className of the elements and I can't e up with the working solution.

Could you please help me with that?

I'm struggling with implementing 'toggle class' functionality in React. I have the NavSidebar ponent which is an unordered list ul. My NavListItem ponent is list item li.

When the list item is clicked I need to give the class name active to the clicked li and other list elements should get an empty class name.

Here's what I've e up with by far:

class NavListItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = { active: false };
  }

  setActive(bool) {
    this.setState({ active: bool });
  }

  render() {
    let index = this.props.key;
    let item = this.props.item;
    return (
      <li className={this.state.active ? 'active' : ''}
          onClick={this.setActive(this.props.setActive).bind(this)} >
        <a href={'#'+item}>{item}</a>
      </li>
    );
  }
}

class NavSidebar extends React.Component {

  constructor(props) {
    super(props);
  }

  render () {

    let items = this.props.navItems.map( (item, index) => {
      return (
        <NavListItem key={index} item={item} setActive={true} />
      );
    });

    return (
        <div className="col-sm-2">
          <nav className="nav-sidebar">
            <ul className="nav">
              {items}
              <li className="nav-divider" />
              <li>
                <a href="#"><i className="glyphicon glyphicon-home"></i> Back Home</a>
              </li>
            </ul>
          </nav>
        </div>
    );
  }
}

NavSidebar.propTypes = {
  navItems: React.PropTypes.array
};

Unfortunately, this doesn't work, it never even touches the className of the elements and I can't e up with the working solution.

Could you please help me with that?

Share Improve this question edited Aug 23, 2015 at 19:17 Denis Yakovenko asked Aug 23, 2015 at 18:43 Denis YakovenkoDenis Yakovenko 3,53511 gold badges54 silver badges90 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

There is no error message here?

onClick={this.setActive(this.props.setActive).bind(this)}

Because you are binding undefined, result of calling this.setActive(this.props.setActive)

and even if you remove the bind, it will not work as the click handler will be undefined. Also, the state should never be modified inside render.

In any case, because you want to update more than one item (the new selected one and the old one), the parent should be responsible of this and should:

  • activate the clicked item
  • deactivate all others
  • re-render the list

Something like this (not tested):

class NavListItem extends React.Component {
  constructor(props) {
    super(props);
  }

  setActive(bool) {
    this.props.onItemActive(this.props.item);
  }

  render() {
    let item = this.props.item;
    return (
      <li className={this.props.active ? 'active' : ''}
          onClick={this.setActive.bind(this)} >
        <a href={'#'+item}>{item}</a>
      </li>
    );
  }
}

class NavSidebar extends React.Component {

  constructor(props) {
    super(props);
    this.state = {activeItem: null};
  }

  onItemActive(item) {
    this.setState({activeItem: item};
  }

  render () {
    let self = this;
    let items = this.props.navItems.map( (item, index) => {
      return (
        <NavListItem key={index} item={item} 
                     onItemActive={self.onItemActive.bind(self)} 
                     active={item === self.state.activeItem} />
      );
    });

    return (
        <div className="col-sm-2">
          <nav className="nav-sidebar">
            <ul className="nav">
              {items}
              <li className="nav-divider" />
              <li>
                <a href="#"><i className="glyphicon glyphicon-home"></i> Back Home</a>
              </li>
            </ul>
          </nav>
        </div>
    );
  }
}

NavSidebar.propTypes = {
  navItems: React.PropTypes.array
};

本文标签: javascriptImplement 39toggle class39 functionality on a list of elements with ReactStack Overflow