640
@640
Beginner

Как скрывать Меню при нажатии вне его поля (Javascript) (React js)?

Вот, есть такой простой компонент меню

class Menu extends Component {

  state = { show: false }

  toggleMenu = () => {
    this.setState({ show: !this.state.show })
  }

  render() {
    const { show } = this.state
    return(
      <div>
        <button onClick={this.toggleMenu}>MENU</button>
        {
          show 
            ? <ul>
                <li>qwe</li>
                <li>asd</li>
                <li>zxc</li>
              </ul>
            : undefined
        }
      </div>
    )
  }
}


Как закрыть меню при нажатии на один из его пунктов, мне известно.
А вот как закрыть меню при нажатии на розовую зону? (То есть, куда угодно, но не на меню)

5c321cf2071bc220802138.png

Есть идея сделать через div, который будет на фоне меню перекрывать все остальные объекты. Сделать его прозрачным, и повесть onClick, который будет прятать меню и этот невидимый div. Как нибудь через z-index.

Но хочется почитать Ваши ответы, Ваши способы.
  • Вопрос задан
  • 72 просмотра
Пригласить эксперта
Ответы на вопрос 2
rockon404
@rockon404
Frontend Developer
Как-то так:
class Menu extends Component {
  state = { isActive: false };
  
  wrapper = React.createRef();
  
  componentWillUnmount() {
    this.removeOutsideClickListener();
  }
  
  addOutsideClickListener() {
    document.addEventListener('click', this.handleDocumentClick);
  }

  removeOutsideClickListener() {
    document.removeEventListener('click', this.handleDocumentClick);
  }
  
  onShow() {
    this.addOutsideClickListener();
  }
  
  onHide() {
    this.removeOutsideClickListender();
  }
  
  onClickOutside() {
    this.setState({ isActive: false });
  }  

  handleDocumentClick = e => {
    if (this.wrapper.current && !this.wrapper.current.contains(e.target)) {
      this.onClickOutside();
    }
  };
  
  toggleMenu = () => {
    this.setState(
      prevState => ({ isActive: !prevState.isActive }),
      () => {
        this.state.isActive ? this.onShow() : this.onHide();
      },
    );
  };

  render() {
    const { isActive } = this.state;

    return(
      <div ref={this.wrapper}>
        <button onClick={this.toggleMenu}>MENU</button>
        {isActive && ( 
          <ul>
            <li>qwe</li>
            <li>asd</li>
            <li>zxc</li>
          </ul>
        )}
      </div>
    )
  }
}
Ответ написан
@grinat
Вешаешь обработчик onclick на window и если туда приходит событие закрываешь меню, в toggleMenu = () => { делаешь toggleMenu = (e) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation();
В общем суть в том что все события они всплывают на самый верх вплоть до window, а чтобы в самом меню оно не всплывало наверх до window ты останавливаешь вспылытие
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Indacoin Москва
от 80 000 до 160 000 руб.
Acme Crypto Corp Нижний Новгород
от 120 000 до 200 000 руб.
19 марта 2019, в 21:07
9000 руб./за проект
19 марта 2019, в 21:06
3000 руб./за проект
19 марта 2019, в 21:00
60000 руб./за проект