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.

Но хочется почитать Ваши ответы, Ваши способы.
  • Вопрос задан
  • 1857 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
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>
    )
  }
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@grinat
Вешаешь обработчик onclick на window и если туда приходит событие закрываешь меню, в toggleMenu = () => { делаешь toggleMenu = (e) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation();
В общем суть в том что все события они всплывают на самый верх вплоть до window, а чтобы в самом меню оно не всплывало наверх до window ты останавливаешь вспылытие
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы