Как сделать так, чтобы все выпадающие меню на странице отслеживали действия кликов пользователя и реагировали на них независимо друг от друга?

Я создал компонент с менюшкой, которая может разворачиваться и сворачиваться при нажатии на нее, а также сворачивалась бы, если кликать за пределами этого компонента.

Смотреть код в песочнице.

Однако, если в приложение вставить два таких компонента с меню или больше, то возникает проблема: если развернуть все менюшки и затем нажать на свободное место в окне приложения, то вместо того, чтобы скрывать все, скроется только то меню, которое было раскрыто последней, а остальные так и останутся открытыми. Как сделать, чтобы в таком случае скрывались сразу все компоненты меню?


Ответы (1 шт):

Автор решения: Макс к

Чтобы эта история работала, нужно состояние закрытие всех вкладок, передать на верх. В вашем случае, в компонент App. Он будет устанавливать статус для всех меню. Можно реализовать вот так:

import React, { useState } from "react";
import Navbar from "./Navbar";
import "./styles.css";

export default function App() {
  let [closeAll, setCloseAll] = useState(false);

let handleCloseAll = (e) => {
  
  if(e.target.className === 'App'){setCloseAll(true)}
   else return
}
let setFalse = () => {
  setCloseAll(false)
}


  return (
    <div className="App"
    onClick = {handleCloseAll}
    >
      <Navbar 
      setFalse = {setFalse}
      closeAll = {closeAll}
      />
      <Navbar 
      setFalse = {setFalse}
      closeAll = {closeAll}
      />
    </div>
  );
}

А компоненты меню, будут сами себя открывать и закрывать и следить, за командой закрытие от компонента Арр. Можно вот так:

import React, { useState, useEffect } from "react";
import cl from "./Navbar.module.css";

const Navbar = (props) => {

  const [isDrop, setIsDrop] = useState(false);
  

  const drop = () => {

  setIsDrop(isDrop => !isDrop) 

  props.setFalse()};

  useEffect(() => {
if(props.closeAll){setIsDrop(false)}
  })

  return (
    <div className={cl.nav}>
      <a onClick={drop}>
        Меню
      </a>
    
      {isDrop ? 
     
      <span >
        <a href="#1">Категория 1</a>
        <a href="#2">Категория 2</a>
        <a href="#3">Категория 3</a>
      </span>: null}
    
    </div>
  );
};

export default Navbar;

→ Ссылка