Employing state management in React to toggle the sidebar

A working example of a sidebar that can be toggled to open/close using CSS, HTML and JavaScript is available.

Link to the Example

The goal is to convert this example to React by utilizing states instead of adding/removing CSS classes.

To ensure the sidebar remains consistent across all pages, a component needs to be passed to render inside the content area.

For instance, the component SidebarColors.js will include another component like this:

<Route exact path="/rendertune" element={ <SidebarColors> <myOtherComponent/> </SidebarColors> } />

In the code below, the imported component will be rendered as {children} on the webpage.

However, issues arise in getting the state management to function correctly within the file.

import React from 'react'
import '../css/SidebarColors.css';

var isSidebarOpen = false;

function sideNavClicked() {
    isSidebarOpen ? closeNav() : openNav();
}

function openNav() {
    isSidebarOpen = true;
    //this.setShowSidebar(true)
    //document.getElementById('mySidebar').classList.add('sidebar-show');
    //this.setMainShow(true)
    //document.getElementById('main').classList.add('main-show');
}

function closeNav() {
    isSidebarOpen = false;
    //this.setShowSidebar(false)
    //document.getElementById('mySidebar').classList.remove('sidebar-show');
    //this.setMainShow(false)
    //document.getElementById('main').classList.remove('main-show');
}

function toggleMenuItem(element) {
    //console.log('toggleMenuItem')
    //this.setSidebarMenuToggle(false)
    // document.getElementById(element.dataset.ulid).classList.toggle("ul-show");
}


const SidebarColors = ({ children }) => {

    const [showSidebar, setShowSidebar] = React.useState(true);
    const [mainShow, setMainShow] = React.useState(true);

    return (
        <>
            <div>
                <button onClick={() => setShowSidebar(true)}>debug button: open sidebar</button>

                <div className="main-content">
                    <div id="mySidebar" className={"sidebar super-animation " + (showSidebar ? "sidebar-show" : "")}>
                        <a href="" className="closebtn" onClick={closeNav}>x</a>
                        <a href="#">About</a>
                        <a data-ulid="expand_this" onClick={toggleMenuItem(this)} href="#">Expand This ▼</a>
                        <ul id="expand_this">
                            <li><a href="#">Coffee</a></li>
                            <li><a href="#">Coverage</a></li>
                        </ul>

                        <a href="#">Clients</a>
                        <a href="#">Contact</a>
                    </div>

                    <div id="main" className={"super-animation" + (mainShow ? "main-show" : "")}>
                        
                        <p>Below is a button to open sidebar</p>
                        <button className="openbtn" onClick={sideNavClicked}>☰</button>

                        <p>main content below</p>
                        {children}
                    
                    </div>
                </div>


            </div>


        </>
    )
}

export default SidebarColors

The use of a constructor was not possible, prompting the need for React.useState. However, invoking functions such as setShowSidebar(true) to add or remove classes from an element did not show any changes on the page.

If there are suggestions on how to utilize state variables effectively to manage CSS classes, input would be appreciated. Thanks.

edit1 Following feedback, updated the code but encountered an error when trying to call openNav() due to Assignment To Constant Variable.

import React from 'react'
import '../css/SidebarColors.css';

const SidebarColors = ({ children }) => {

    const [isSidebarOpen, setIsSidebarOpen] = React.useState(false);
    const [showSidebar, setShowSidebar] = React.useState(true);
    const [mainShow, setMainShow] = React.useState(true);

    function sideNavClicked() {
        console.log('isSidebarOpen = ', isSidebarOpen)
        isSidebarOpen ? closeNav() : openNav();
    }

    function openNav() {
        console.log('openNav')
        isSidebarOpen = true;
        this.setShowSidebar(true)
        //document.getElementById('mySidebar').classList.add('sidebar-         show');
        //this.setMainShow(true)
        //document.getElementById('main').classList.add('main-show');
    }

    function closeNav() {
        console.log('closeNav')
        isSidebarOpen = false;
        this.setShowSidebar(false)
        //document.getElementById('mySidebar').classList.remove('sidebar-         show');
        //this.setMainShow(false)
        //document.getElementById('main').classList.remove('main-show');
    }

    function toggleMenuItem(element) {
        //console.log('toggleMenuItem')
        //this.setSidebarMenuToggle(false)
        // 
        //document.getElementById(element.dataset.ulid).classList.toggle("ul-show");
    }

    return (
        <>
            <div>
                <button onClick={() => setShowSidebar(true)}>debug button: open sidebar</button>

                <div className="main-content">
                    <div id="mySidebar" className={"sidebar super-animation " + (showSidebar ? "sidebar-show" : "")}>
                        <a href="" className="closebtn" onClick={closeNav}>x</a>
                        <a href="#">About</a>
                        <a data-ulid="expand_this" onClick={toggleMenuItem(this)} href="#">Expand This ▼</a>
                        <ul id="expand_this">
                            <li><a href="#">Coffee</a></li>
                            <li><a href="#">>Coverage</a></li>
                        </ul>

                        <a href="#">Clients</a>
                        <a href="#"&t;Contact</a>
                    </div>

                    <div id="main" className={"super-animation" + (mainShow ? "main-show" : "&tquot;")}>
                        
                        <p>Below is a button to open sidebar</p>
                        <button className="openbtn" onClick={sideNavClicked}>⮞</button>

                        <p>t;main content below&t;/p>
                        {children}
                    
                    </div>
                </div>


            </div>


        </>
    )
}

export default SidebarColors

Answer №1

One reason for the issue could be that regular variables are being used to set state in React components, which prevents them from re-rendering. To update UI components on your page, make sure to maintain their state properly. Additionally, using the this keyword in a functional component is incorrect and should be removed.

const SidebarColors = ({ children }) => {
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
  
  const [showSidebar, setShowSidebar] = React.useState(true);
  const [mainShow, setMainShow] = React.useState(true);

  function sideNavClicked() {
    isSidebarOpen ? closeNav() : openNav();
  }

  function openNav() {
    setIsSidebarOpen(true);
    setShowSidebar(true)
    document.getElementById('mySidebar').classList.add('sidebar- 
    show');
    setMainShow(true)
    document.getElementById('main').classList.add('main-show');
  }

  function closeNav() {
    setIsSidebarOpen(false);
    setShowSidebar(false)
    document.getElementById('mySidebar').classList.remove('sidebar- 
    show');
    setMainShow(false)
    document.getElementById('main').classList.remove('main-show');
  }

  function toggleMenuItem(element) {
    console.log('toggleMenuItem')
    setSidebarMenuToggle(false)
    
  document.getElementById(element.dataset.ulid).classList.toggle("ul- 
  show");
  }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensure accurate detection of invalid values for SVG Elements in React using jest testing framework

When testing my react app, I am attempting to capture any errors that are thrown or logged to the console. If a regular HTML element such as <p> contains invalid attributes like <p color={false}></p>, react will display an error via cons ...

What is the difference in performance between using named functions versus anonymous functions in Node.js?

Currently, I am working on a Node.js app and was initially using anonymous functions for callbacks. However, after referring to the website callbackhell.com, I discovered that using named functions is considered best practice for coding. Despite switching ...

Looking for a list of events in Express.js?

I've been searching through the official documentation, but I couldn't find a list of events for express. Does anyone know if there's something like 'route-matched' so that I can use app.on('route-matched', () => {})? ...

Image broken despite accurate file path in next.js and tailwind

https://i.stack.imgur.com/2ZqPa.png In my components folder, specifically in navbar.js, I have a path to the image folder <img className="block lg:hidden h-8 w-auto" src='../images/logo_injoy.png' alt="Logo" /> U ...

Any advice on dealing with authentication issues in React when using Firebase?

I am working on creating a user authentication page in react using firebase. I am able to sign in successfully, but the sign in button does not change to sign out after signing in. Can anyone help me diagnose the issue? const handleAuthentication ...

Is Nextjs the best choice for developing the frontend code exclusively?

When deciding whether to use Next.js or plain React for my front-end development, should I consider that a back-end already exists? If I am not planning to write a new back-end, which option would be better suited for the project? ...

Select from a list to save

My goal is to create a feature where users can select a hotel name, number of days, guests, and peak time, the system will calculate them together and give a sum. Furthermore, I wish to store all user selections in the database, including the calculated to ...

Creating an Array module in Node JS

Adding a prototype to the Array class can be done in native javascript with the following code: var myArray = Array; myArray.prototype.myMethod = function(){} var testArray = new myArray(); testArray.contains(); Now I need to achieve this using a nod ...

Ways to prompt the debugger to pause whenever a specific script file is called during execution in Edge/Chrome debugger

I am currently in the process of debugging a Typescript web application, which is quite new to me as I have never delved into web development before. This particular project entails multiple script files and various libraries. While running the applicatio ...

Add a date to my database using an HTML form

I am having trouble inserting a date into my database using PHP. Everything else inserts correctly, but the date reverts to the default 0000-00-00 as if nothing was entered. I have set the data type for the date field. Here is the code snippet: <?php ...

Is there a way to display a div element just once in AngularJS?

I only want to print the div once and prevent it from printing again. $scope.printDiv = function(divName) { var printContents = document.getElementById(divName).innerHTML; var popupWin = window.open('', '_blank', 'width=300, ...

Can you use ng-show within ng-if in Angular?

How can I make this input only show a property is true per the ng-if? The current code looks like this: <input type="button" class="naviaBtn naviaBlue" ng-if="ppt.Globals.hasDebitCard" ng-click="alertShow = (alertShow == 2 ? -1 : 2)" value="outstandin ...

Tips for transitioning from mui v4 to mui v5 styling

I'm struggling to figure out how to future-proof my styling migration from Material-UI v4 to v5. It appears that MUI has transitioned to using Emotion for its styling in v5, which means the old styling methods used in v4 are no longer supported. It se ...

Show an image within a textview using the <img> tag in HTML

I'm trying to show an image in a textview using HTML. I have placed the image at res/drawable/img.png and here is the code I am using: String img="<img src='file:///res/drawable/img.png' />"; txt_html.append(Html.fromHtml(img)); Howe ...

Unfortunately, the input type number does not allow for the removal of decimal points

I need assistance with modifying the HTML code below. I want to remove the decimal point from the input field. Could anyone please provide instructions on how to accomplish this? <input type="number" min="0" step="1" ng-pattern="/^(0|[1-9][0-9]*)$/" ...

Utilizing Angular JS to parse JSON data and showcase it in various tables

Just diving into Angular JS and looking for some guidance. Can someone show me how to parse and showcase JSON Data in separate tables using Angular JS? [ { "id": 0, "isActive": false, "balance": 1025.00, "picture": "htt ...

Is it time to swap out those divs for tables in your email template?

I have set up my template like this and I am questioning whether I should replace every div with a table. Let's start with the first div in the example. Do I really need to create a new table element, followed by tr and td tags just for a banner? I u ...

Invoking a JavaScript function within a different JavaScript function

Is there a way to ensure that the JavaScript function works properly even when using a text editor? var editor = $('#CKEditor1').ckeditorGet(); editor.on("instanceReady", function () { this.document.on("keydown", function (event) { ...

Update tag information

Hi there! I'm encountering an issue with my Pokedex. After selecting the number of cards to display on the page, I need to reload a container with the new set of cards. Could you assist me with this? For selecting items, I understand that I should us ...

Updating a column in a SQL Table via an Ajax request

I am attempting to store the on or off value from a form into an SQL database by calling a JS function with an AJAX request that sends it to a PHP page for processing. I seem to be facing some issues with my code and could really use some assistance as the ...