Home > front end >  Merging 2 functions into one / sharing use state
Merging 2 functions into one / sharing use state

Time:10-29

I am using react and typescript and I have two functions that do similar things except they use a different data set and also call two different functions. I have tried to merge them into one because the purpose of them is that if one sub-menu is open and I open another sub-menu then the first submenu will close. As they are separate when I open a sub-menu in one I can open a sub-menu in the other as well which I don't want.

I tried to merge by turning it into a single function and using an if statement and passing a string reflecting "dashboard" or "analysis" but I couldn't get it to work and it just completely broke my code. I was wondering if anyone could help me merge my functions or at least share the state of if a sub-menu is opened/closed so only one sub-menu can only be open at any given time across both sections.

const DashboardsOpen = () => {
    const items = DashboardHeaders;
    const [openId, setOpenId] = useState<number | null>(null);
  
    const toggleHandler = (id: number) => () => {
      setOpenId(openId => openId === id ? null : id);
    };
    
    return ( 
    <div className="Sub-Menu-Items-Container">
         {items.map((item) => ( 
         <div key={item.id}> 
          <DashboardItems item={item} open={openId === item.id} onClick={toggleHandler(item.id)} />
         </div> 
         ))}
    </div> 
    )
}

The second function has two unique features which are Analysis Headers and calls the function AnalysisItems.

const AnalysisOpen = () => {
   
   const items = AnalysisHeaders;
   const [openId, setOpenId] = useState<number | null>(null);
 
   const toggleHandler = (id: number) => () => {
    
     setOpenId(openId => openId === id ? null : id);
   };
   
   return ( 
       
   <div className="Sub-Menu-Items-Container">
        {items.map((item) => ( 
        <div key={item.id}> 
         <AnalysisItems item={item} open={openId === item.id} onClick={toggleHandler(item.id)} />
        </div> 
        
        ))}
        
        
   </div> 
   )
 }

Main Wrapper which calls the functions

            <div className="Side-Pannel-Navigation-Main-Wrapper-Open">
                <Overview/>
                <div className="Side-Pannel-Section-Title">Dashboards</div>
                <DashboardsOpen/>             
                <div className="Side-Pannel-Section-Title">Analysis</div>
                <SearchBar placeholder="Search...." data={SearchData}/>
                <AnalysisOpen/>
            </div>

CodePudding user response:

If I understood correctly, you are trying to make two sub-menus where when one is open the other one is closed, and vice-versa. Right now, you are using two separate functions that both manage which id is open, but because they do it in their own functions they don't sync with each other which doesn't allow you to force one to stay open and the other closed.

I think instead of making each of them manage which id is open, you should make the Main Wrapper do it. You could simply send down the state to <AnalysisOpen/> and <DashboardsOpen/>. That is, something like this:

Main Wrapper

/* ... */

    const [openId, setOpenId] = useState<number | null>(null);
  
    const toggleHandler = (id: number) => () => {
     
      setOpenId(openId => openId === id ? null : id);
    };

    return (
        <div className="Side-Pannel-Navigation-Main-Wrapper-Open">
            <Overview/>
            <div className="Side-Pannel-Section-Title">Dashboards</div>
            <DashboardsOpen openId={openId} setOpenId={setOpenId}/>             
            <div className="Side-Pannel-Section-Title">Analysis</div>
            <SearchBar placeholder="Search...." data={SearchData}/>
            <AnalysisOpen openId={openId} setOpenId={setOpenId}/>
        </div>
    );

/* ... */

AnalysisOpen and DashboardsOpen

const xxxxxx = ({openId, setOpenId}: any) => {
   
   const items = AnalysisHeaders;
 
   const toggleHandler = (id: number) => () => {
     setOpenId(openId => openId === id ? null : id);
   };
   
   return ( 
       /* ... */
   )
 }

Doing it like this will ensure only one is displayed at a time.

  • Related