title: React toggle responsive sidebar based on browser width &/or user clicks
body: <p>React noob here. I am creating a dashboard with three parts. Sidebar | Navbar &amp; content below navbar.
  Sidebar behavior should be: open initially; auto-hide when browser-width &lt; 498px; auto-open when browser width is increased beyond 498px; open/close when navbar toggle is hit, regardless of browser window width (ie., mobile or desktop).
  I know how to do this in jQuery but want to learn React way. Searching the forums and Google, I created a working model. However, I sense that the code can be simplified or at least audited for issues. Hoping for some senior enlightenment, all help is welcomed. Worried about dependency warnings and calling of 2 handlers. Did not use addEventListener as I read Safari may have issues.
  <strong>Notes</strong>, I avoided using css media query for auto-hide, as I could not figure out how to override css file media query of <code>display:none</code> from React when click component is used. Using react 17.0.2; bootstrap 5.1.3;</p>
  <p><code>Dashboard.js</code></p>
  <pre><code>import { useEffect, useRef, useState } from 'react';
  import &quot;./Dashboard.css&quot;;
  import Navbar from &quot;./Navbar&quot;;
  import Sidebar from &quot;./Sidebar&quot;;
  
  const Dashboard = () =&gt; {
  const sidebarRef = useRef(null); // used to get sidebar width
  const [usMobile, setMobile] = useState(&quot;&quot;);
  const mq = window.matchmedia(&quot;(max-width: 498px)&quot;);
  const [firsTime, setFirsTime] = useState(true);
  
  useEffect(() =&gt; {
    //handle sidebar display clicks from Navbar
    // makes/sets initial sidebar state to open
    // returns true when window is &lt; 498px
    // unmount cleanup handler
    toggleSidebar();
    mq.addListener(toggleSidebar);
    return () =&gt; mq.removeListener(toggleSidebar);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // warning about dependency here
  
  useEffect(() =&gt; {
    // handles sidebar display based on resize
    // returns treu when window is &lt; 498
    mq.addListener(hideSideBar);
    return () =&gt; mq.removeListener(hideSideBar);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // warning about dependency here
  
  const hideSideBar = () =&gt; {
    if(mq.matches) { 
      setMobile(true);
    } else {
      setMobile(false);
    }
  }
  
  // toggle sidebar based on user clicks
  const toggleSidebar = ( clicked ) =&gt; {
    let sidebarWidth = sidebarRef.current.offsetWidth;
    if (firsTime) {
       setShowSidebar(true);
       setMobile(false);
       setFirstTime(false);
    } else {
       if ( clicked = &quot;yes&quot;) {
          if (sidebarWidth == 0){
             setShowSidebar(true);
             setMobile(false);
          } else {
             setShowSidebar(false);
          }
          clicked = &quot;&quot;;
       }
    }
  }
  
  return (
    &lt;span ref={sidebarRef}&gt;
      {!isMobile &amp;&amp; showSidebar &amp;&amp; &lt;Sidebar onClick={toggleSidebar} /&gt;}
    &lt;/span&gt;
    &lt;div className=&quot;flex-fill content-wrapper&quot;&gt;
      &lt;Navbar showSideBar={showSidebar} onClick={toggleSidebar} /&gt;
    &lt;/div&gt;
  );
  }
  
  export default Dashboard;
  </code></pre>
  <p><code>Navbar.js</code></p>
  <pre><code>import {useState} from 'react';
  
  const Navbar = (props) =&gt; {
    // eslint-disable-next-line no-unused-vars
    // set is unused but it will not work otherwise
    const [clicked, setClicked] = useState(&quot;yes&quot;); 
  
    return (
      &lt;div className=&quot;d-flex justify-content-between bg-white py-2 ps-3 pe-4&quot;&gt;
        &lt;div className=&quot;col-auto&quot;&gt;
          &lt;button 
              className=&quot;menu-icon-btn&quot;
              onClick={() =&gt; props.onClick(clicked)} &gt;
          &lt;/button&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  )
  }
  export default Navbar;
  </code></pre>
  <p><code>Sidebar.js</code></p>
  <pre><code>import {useState} from 'react';
  
  const Sidebar = (props) =&gt; {
    const [clicked, setClicked] = useState('yes');
  
    return (
      &lt;div className=&quot;d-flex flex-column flex-shrink-0 text-white bg-dark sidebar&quot;&gt;
        &lt;span className=&quot;fs4&quot;&gt;Sidebar Title&lt;/span&gt;
        &lt;ul className=&quot;nav nav-pills flex-column mb-auto&quot;&gt;
          &lt;li className=&quot;nav-item&quot;&gt;
              Home
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;hr&gt;
        &lt;span id=&quot;toggle-x&quot;
              className=&quot;btn btn-outline-primary border-0 inline d-md-none mx-auto mb-2&quot;&gt;
              aria-label=&quot;Toggle Sidebar Nav&quot;
              onClick={() =&gt; props.onClick(clicked)} &gt;
                CLOSE
         &lt;/span&gt;
      &lt;/div&gt;   
    )
  }
  
  export default Sidebar;
  </code></pre>
  <p><code>Dashboard.css</code>
  Most all css is from bootstrap; these are just app custom styles</p>
  <pre><code>.menu-icon-btn {
    background: none;
    border: none;
    padding: 0;
  }
  
  .toggle-icon {
    width: 32px;
    height: 32px;
    fill: var(--medium-gray);
    cursor: pointer;
  }
  
  .menu-icon {
    width: 20px;
    height: 20px;
    fill: var(--medium-gray);
    cursor: pointer;
  }
  
  .sidebar,
  .content-wrapper {
    height: 100vh;
  }
  
  .sidebar-wrapper {
    width: 200px;
  }
  /* Omitted the following as I was unable to force it to change from within React. In jQuery(show/hide seem to override this just fine.)*/
  /* @media screen and (min-width: 0px) and (max-width: 700px) {
    .sidebar-wrapper {
      display: none;
    }
  } */
  </code></pre>
  <p><code>New Dashboard.js</code></p>
  <pre><code>const Dashboard = () =&gt; {
      const isDesktop = () =&gt; window.innerWidth &gt; 598;
      const [sidebarStatus, setSidebarStatus] = useState(&quot;&quot;);
  
      useEffect(() =&gt; {
          window.addEventListener(&quot;resize&quot;, () =&gt; {
              setSidebarStatus(isDesktop());
          });
          return () =&gt; window.removeEventListener(&quot;resize&quot;, isDesktop);
      }, []);
  
      const toggleSidebar = (open) =&gt; {
          setSidebarStatus(open);
      };
  
      return (
      
          {sidebarStatus &amp;&amp; (
            &lt;Sidebar showSideBar={sidebarStatus} onClick={toggleSidebar} /&gt;
          )}
  
      )
  }
  </code></pre>
  <p><code>New Navbar.js</code></p>
  <pre><code>const Navbar = (props) =&gt; {
  
  return (
          &lt;button
            id=&quot;toggle&quot;
            className=&quot;menu-icon-btn py-2&quot;
            data-menu-icon-btn
            onClick={() =&gt; props.onClick(!props.showSideBar)}
          &gt; Toggle Sidebar
          &lt;/button&gt;
  )
  }
  
  
  </code></pre>