Задать вопрос
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.

Но хочется почитать Ваши ответы, Ваши способы.
  • Вопрос задан
  • 1920 просмотров
Подписаться 1 Простой Комментировать
Помогут разобраться в теме Все курсы
  • Яндекс Практикум
    React-разработчик
    3 месяца
    Далее
  • ProductStar
    React: отточите навыки интерфейсной разработки
    6 недель
    Далее
  • Skillfactory
    Специализация Frontend-разработчик
    9 месяцев
    Далее
Решения вопроса 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 ты останавливаешь вспылытие
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы
ITK academy Нижний Новгород
от 50 000 до 90 000 ₽
IT ATLAS Москва
от 200 000 до 250 000 ₽
ITK academy Казань
от 50 000 до 90 000 ₽