abbey
abbey

Reputation: 223

how to handle click only one <li> item in react

First, Sorry for my Bad English. I want to make a category tree component and blew is my rendering code.

class tree extends Component {
constructor(props) {
    super(props);
    this.state = {
        showBig1: false,
        showBig2: false,
        showSmall1: false,
        showSmall2: false,
        current: 'fake',
        fake: false
    };

}

toggleBigMenu = (type, current_now) => {
    this.state = {
        [current_now]: false,
        [type]: true,
        current: type
    }
}


render() {
    const {showBig1, showBig2, showSmall1, showSmall2} = this.state
    return (
        <div>
            <li className={showBig1 ? "on" : "off"} onClick={this.toggleBigMenu("showBig1", current)}>
                <Link to="#">
                    <span>BIG MENU 1</span>
                </Link>
            </li>
            <li className={showBig2 ? "on" : "off"} onClick={this.toggleBigMenu("showBig2", current)}>
                <Link to="#">
                    <span>BIG MENU 2</span>
                </Link>
                <ul>
                    <li className={showSmall1 ? "on" : "off"} onClick={this.toggleBigMenu("showSmall1", current)}>
                        <Link to="#">
                            <span>SMALL MENU 1</span>
                        </Link>
                    </li>
                    <li className={showSmall2 ? "on" : "off"} onClick={this.toggleBigMenu("showSmall2", current)}>
                        <Link to="#">
                            <span>SMALL MENU 2</span>
                        </Link>
                    </li>
                </ul>
            </li>

        </div>
    )
}

}

and I want to click only one 'li' item at a time. But When I click BIG MENU1, it clicked with BIG MENU 2. And BIG MENU 2's state turn true, but I want to turn BIG MENU 1's state.

I don't know how to solve it.. please anyone help me. Thank you.

Upvotes: 3

Views: 4901

Answers (1)

Tholle
Tholle

Reputation: 112917

By writing onClick={this.toggleBigMenu("showBig1", current)} you are invoking this.toggleBigMenu directly on render. You can create a new function that will be invoked when the event occurs instead.

Instead of passing in current every time you change menu, you can reset all menus to being false and just setting the clicked one to true.

Since you have menus inside other menus, it's also a good idea to call event.stopPropagation() on the click event so the nested menus have a chance of being selected.

Example

const menus = {
  showBig1: false,
  showBig2: false,
  showSmall1: false,
  showSmall2: false
};

class Tree extends React.Component {
  state = { ...menus };

  toggleMenu = (event, type) => {
    event.stopPropagation();

    this.setState({
      ...menus,
      [type]: true
    });
  };

  render() {
    const { showBig1, showBig2, showSmall1, showSmall2, current } = this.state;

    return (
      <div>
        <li
          style={{ backgroundColor: showBig1 ? "green" : "red" }}
          onClick={event => this.toggleMenu(event, "showBig1")}
        >
          <span>BIG MENU 1</span>
        </li>
        <li
          style={{ backgroundColor: showBig2 ? "green" : "red" }}
          onClick={event => this.toggleMenu(event, "showBig2")}
        >
          <span>BIG MENU 2</span>
          <ul>
            <li
              style={{ backgroundColor: showSmall1 ? "green" : "red" }}
              onClick={event => this.toggleMenu(event, "showSmall1")}
            >
              <span>SMALL MENU 1</span>
            </li>
            <li
              style={{ backgroundColor: showSmall2 ? "green" : "red" }}
              onClick={event => this.toggleMenu(event, "showSmall2")}
            >
              <span>SMALL MENU 2</span>
            </li>
          </ul>
        </li>
      </div>
    );
  }
}

ReactDOM.render(<Tree />, document.getElementById("root"));
<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>

Upvotes: 3

Related Questions