Search code examples
reactjsreact-three-fiber

Show one div hide another onclick in ReactJS


Quite new to ReactJS and using it for web development. How do I show one div but hide all others onclick, all divs are hidden on purpose (popup divs from onclick on sidebar menu).

I have two buttons on a side panel and two divs that are hidden on page load. Currently I have each of them hiding/showing onclick but the problem is if one is opened when the other is opened then they both appear which is not what I want (as they cover each other)

Current code:


export default function LoginBox() { 
  const [show, setShow] =  useState(false);
  const [showControls, setShowControls] =  useState(false);

  return (
    <>

<div id="sidebarLeft" className="hideBar">
        <div className="leftBarDetails">
          
          <div className="home topButton">
            <div className="sideButtonIcon" 
            
            onClick={()=>{setShow(!show)}}
            
            >
              <i className="fa-solid fa-user"></i>
            </div>
          </div>
          <div className="home topButton">
            <div className="sideButtonIcon" onClick={()=>{setShowControls(!showControls)}}>
              <i className="fa-solid fa-gamepad"></i>
            </div>
          </div>
    
        </div>
      </div>
     {show && <div className="logincontainer hidden">
            <label className="close-btn fas fa-times" onClick={()=>{setShow(!show)}}></label>
            <div className="text">Login Form</div>
            <form action="#">
              <div className="data">
                <label>Email</label>
                <input type="text" required />
              </div>
              <div className="data">
                <label>Password</label>
                <input type="password" required />
              </div>
              <div className="forgot-pass">
                <a href="#">Forgot Password?</a>
              </div>
              <div className="btn">
                <div className="inner"></div>
                <button type="submit">login</button>
              </div>
              <div className="signup-link">
                Need an account?
                <a href="#"> Signup now</a>
              </div>
            </form>
          </div>}
     {showControls && <div className="logincontainer hidden">
            <label className="close-btn fas fa-times" 
            onClick={()=>{setShowControls(!showControls)}}>

            </label>
            <div className="text"> <p>
              <b>CONTROLS</b>
              :<br />
              <b>WASD || ARROW KEYS</b>
              - Move<br />
              <b>R|F || SPACEBAR | SHIFT</b>
              - Up | Down<br />
            </p></div>
            
          </div>}

After some research and assistance from chatgpt I solved my issue with the following code:


import { useState } from "react";

export default function LoginBox() {
  const [show, setShow] = useState('');
  const [sidebarActive, setSidebarActive] = useState(false);

  const handleClick = (id) => {
    if (show === id) {
      setShow('');
      setSidebarActive(false);
    } else {
      setShow(id);
      setSidebarActive(true);
    }
  };

  const handleParentClick = () => {
    if (sidebarActive) {
      setShow('');
      setSidebarActive(false);
    }
  };

  return (
    <>
      <div id="sidebarLeft" className={`hideBar ${sidebarActive ? 'active' : ''}`}>
        <div className="leftBarDetails">
        
          <div className="home topButton" onClick={() => handleClick('login')}>
            <div className="sideButtonIcon">
              <i className="fa-solid fa-user"></i>
            </div>
          </div>
          <div className="home topButton" onClick={() => handleClick('controls')}>
            <div className="sideButtonIcon">
              <i className="fa-solid fa-gamepad"></i>
            </div>
          </div>
        </div>
      </div>

      {show === 'login' && (
        <div className="logincontainer hidden" onClick={handleParentClick}>
          <label className="close-btn fas fa-times" onClick={() => setShow('')}></label>
          <div className="text">Login Form</div>
          <form action="#">
            <div className="data">
              <label>Email</label>
              <input type="text" required />
            </div>
            <div className="data">
              <label>Password</label>
              <input type="password" required />
            </div>
            <div className="forgot-pass">
              <a href="#">Forgot Password?</a>
            </div>
            <div className="btn">
              <div className="inner"></div>
              <button type="submit">login</button>
            </div>
            <div className="signup-link">
              Need an account? <a href="#"> Signup now</a>
            </div>
          </form>
        </div>
      )}

      {show === 'controls' && (
        <div className="logincontainer hidden" onClick={handleParentClick}>
          <label className="close-btn fas fa-times" onClick={() => setShow('')}></label>
          <div className="text">
            <p>
              <b>CONTROLS</b>:<br />
              <b>WASD || ARROW KEYS</b> - Move<br />
              <b>R|F || SPACEBAR | SHIFT</b> - Up | Down<br />
              <b>LEFT CLICK AND MOUSE</b> - Camera Movement<br />
              <b>ESC</b> - Exit Camera Movement<br />
            </p>
          </div>
        </div>
      )}  
    </>
  );
}

Thanks everyone for the help anyway and I hope it helps someone else


Solution

  • There are several ways to solve this, for example you can add two useEffect hooks that will check whether the other divs are shown and hide them accordingly:

    useEffect(() => {
      if (show) {
        setShowControls(false);
      }
    }, [show]);
    
    useEffect(() => {
      if (showControls) {
        setShow(false);
      }
    }, [showControls]);
    

    And don't forget to add the import:

    import { useEffect } from 'react';
    

    Another option is to add this logic in the onClick functions directly:

    <div className="home topButton">
      <div
        className="sideButtonIcon"
        onClick={() => { 
        // This check ensures the other div will hide if previously shown
          if (showControls) {
            setShowControls(false);
          }
          setShow(!show);
        }}
      >
        <i className="fa-solid fa-user"></i>
      </div>
    </div>
    

    And:

    <div className="home topButton">
      <div
        className="sideButtonIcon"
        onClick={() => {
        // This check ensures the other div will hide if previously shown
          if (show) {
            setShow(false);
          }
          setShowControls(!showControls);
        }}
      >
        <i className="fa-solid fa-gamepad"></i>
      </div>
    </div>