What is the best way to change the class name using useState in order to trigger the required CSS conditions? Updating the tab ID appears to be

Just starting out with react/typescript (my third project).

I'm currently working on a custom dynamic tab component. In this component, I dynamically create a class name to determine which tab is active and which is not. It seems to be functioning properly, but upon closer inspection, there are some errors.

The goal is to add a background color when the active tab is clicked to indicate to the user that it's the tab they're currently viewing. The full code is provided below, but I've highlighted the issues in these sections:

  1. I've set up a state that changes based on the clicked tab. When a tab is clicked, the active tab state is updated to match the current tab's index. However, although the logic seems sound, the console shows that the active tab id doesn't always match the current tab's index.
    const [btnState, setBtnState] = useState({activeTabId: 0});
    const onClick = (id:number) => {
            setBtnState({activeTabId:id})       
        
           console.log(btnState.activeTabId, id);
          };
  1. After researching online resources, it became clear that the state wasn't updating instantaneously. Once I made adjustments, the console log showed that the active id was now being updated correctly with the current tab. However, the CSS behavior wasn't as expected - instead of changing the class name to "active tab" when clicking on the current tab, it would only display on the previous tab.

    const [btnState, setBtnState] = useState({activeTabId: 0});
    const onClick = (id:number) => {
            btnState.activeTabId = id
            setBtnState(btnState)       
        
         console.log(btnState.activeTabId, id);
          };

Can anyone shed light on what might be going wrong? Why does the first approach work despite the inaccurate active id, while the second one somewhat works with the correct active id? The problematic tag here is <li>

import React, { ReactNode } from "react"
import { useState } from "react"

function MyComponent (props: ComponentProps) {
    
  const [tab, setTab] = useState([{ title: ""}])
  const [btnState, setBtnState] = useState({activeTabId: 0});

  const newTab = () => {
    setTab([...tab, {title: ""}])

  }

  const deleteTab = (index:number) => {
    const list = [...tab]
      list.splice(index, 1)
      setTab(list)

  }

  const handleTabChange = (e:React.ChangeEvent<HTMLInputElement>, index:number) => {
    const {name, value} = e.target
    const list = [...tab]
    list[index][name] = value
    setTab(list)
  
  }

const updateActiveId= (id:number) => {
    setBtnState({activeTabId:id})       

    console.log(btnState.activeTabId, id);
  };


const activeNav = (id:number) => {
    if (id === btnState.activeTabId) {
      return "individual-tab-container tab-selected";
    } else {
      return "individual-tab-container";
    }
  };  


return (
    <div className="dynamic-tabs">
      <ul className="all-tabs">
      {tab.map((tabTitle, index) => (
        <span className="dynamic-tab-container">
        <li key={index} onClick={() => updateActiveId(index)} className={activeNav(index)}> 
          <span className="title-close-save-button-container">
            <input className="title-of-tab" 
                    name="title"
                    type="text"
                    required
                    placeholder="Click to rename tab here" 
                    size={20}
                    maxLength={20}
                    value = {tabTitle.title}
                    onChange={(e) => handleTabChange(e, index)}/>    
                    
            <div className="save-close-btn-container">
            <div className="save-button-container">
              <button id="save">save</button></div>
            <div className="close-btn-container"> 
            <button type="button" className="close-btn" onClick={() => deleteTab(index)}>
              <div className="close-btn-txt">&times;</div>
              </button>   
              
              </div> 
              </div>  
            </span>       
          </li>   
          </span>
    ))}
  </ul>
    <span className="new-tab-btn-container">
      <button type='button' className="new-tab-btn" onClick={newTab}>
      <i className="material-icons" id="add-btn">add</i></button>
    </span>
    


    </div>
  )
}

CSS - used for testing the functionality of the active tab

.dynamic-tabs{
    position: relative;
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    height: 120px;
    border: 2px solid green;
    width:94%;
            
}

.dynamic-tab-container{
    display: flex;
}

 li {
    list-style-type: none;
 }

.all-tabs{
    display: flex;
    height: 80px;
}

.dynamic-tab-container{
    border-bottom: 2px solid #d3d2d2;
    border-right: 2px solid black;
    border-left: 2px solid black;
    border-top: 2px solid black;
    margin-top: 7px;
    height: 110%;
    width: 360px;
}

.title-close-save-button-container{
    display: flex;
    margin-top:6.5%;
    flex-flow: row; */
}

input{
    margin-left:2%;
    margin-top:4%;
    border:none;
    font-family: 'Hi Melody', cursive;
    font-size: 14px;
    font-weight:500;
}


input:focus{
    outline:none;
}

button{
    background: none;
    border: none;
}

button:active{
    outline: none;
}

button:focus{
    outline: none;
}

.save-close-btn-container{
    display: flex;
    margin-left: 16%;
    margin-top: 4%;
    transition: margin-left 200ms;
    font-family: 'Hi Melody', cursive;
    font-weight:300;
}

.new-tab-btn-container{
    display: flex;
    position: fixed;
    margin-left: 95%;
    top:7%;
    height:60px;
    border-right: 2px solid black;
    border-left: 2px solid black;
    border-top: 2px solid black;
    border-bottom: 2px solid black; 
}

.tab-selected{
    background-color: red;
}

Answer №1

You have the option to utilize the className parameter as a JSX element. Here is a brief example:

  const CustomComponent = () => {
    const [flag, setFlag] = useState(false);

    return (
      <button 
        className={flag ? 'class-with-flag' : 'class-without-flag'} 
        onClick={() => setFlag(currentState => !currentState)} 
      >
        Click Me
      </button>
    )
  }

The className parameter functions in the same way as the class HTML attribute, but since class is a reserved keyword in JavaScript, React had to use a different name for it.

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

What methods are available in JavaScript for determining the width of a section and implementing proper spacing for a menu?

Is it possible to use Javascript to dynamically adjust the size of each <li> element within the menuArea so that they fill the entire space correctly? // Could we achieve this with the following code... var menuSpace = Math.floor((menuAreaWidth ...

Assigning the XSL value as an identifier for the element

I'm attempting to generate an HTML file from XML by using XSLT. One of the challenges I'm facing is utilizing a value extracted from the XML as an ID for a specific element on the page. Unfortunately, the XSL fails to compile when I attempt this. ...

Can anyone assist me with creating a custom sorting pipe in Angular 2?

*ngFor="let match of virtual | groupby : 'gameid' I have this code snippet that uses a pipe to group by the 'gameid' field, which consists of numbers like 23342341. Now, I need help sorting this array in ascending order based on the g ...

Angular: merging object values into a single string by looping over them

i am dealing with the following data : "commercialRanges": [ { "rangeId": "700", "rangeName": "POSTPAID" }, { "rangeId": "500", "rangeName": "PREPAID" }, ] In my view, I am aiming to display the ...

I'm looking to create a JavaScript function that will extract each element from a div and then apply a corresponding CSS block to activate it

My goal was to create this function using Flask, but it seems that only JavaScript is capable of achieving it. This is my first attempt at coding it. Here's the code snippet: const navSlide2 = () => { const burger = document.querySelector(&apos ...

Tips for enhancing your HTML email template with borders:

I designed an email template using the email template editor and incorporated nested table tags for each mail element. As I created a table to contain all these elements and attempted to add borders to the tags, I encountered a space between the top and bo ...

Unable to integrate Express.js into my React JS project

Having trouble integrating express.js into my react js Project. After adding the following lines to my app.js code: const express = require('express') const app = express(); I encounter the error messages below: - Module not found: Error: Can&ap ...

How can I determine the element that has been clicked or focused within the blur event of a separate element?

Within my react application, I have implemented a blur event listener. In the function associated with this listener, I am seeking a way to determine which element received focus. Is there a method to achieve this specifically in Chrome browser? Below is ...

The primary container is brimming with an abundance of content

Can anyone help me with a CSS issue I'm experiencing in the latest versions of Chrome and Firefox? I can't seem to figure it out on my own. The problem arises with a container div that has a 50px top margin. Inside this container, there's a ...

Using AngularJs: Implementing xeditable injection and utilizing a separate controller

I am looking for something similar to the example provided here http://jsfiddle.net/NfPcH/93/ Here is how I implement it: (function() { 'use strict'; angular .module('myapp') .controller('MyCtrl', Projec ...

Adjust website layout for screens less than 320px in width

Struggling to complete my project and having trouble figuring out how to scale my website for screens smaller than 320px, even though they are rare. I admire the solution used by Apple where the website freezes and scales down while maintaining its origin ...

Have I potentially compromised my project by executing the command `npm audit fix --force`?

While working on a React project using Vite, everything was going smoothly. I decided to incorporate some charts and came across the recharts package, which I found quite appealing. So, I added it to my project using the command npm i recharts. After runn ...

Error message: Conflicting type declarations across multiple files

I am facing a challenge with my TypeScript 'snippets' project. It seems that multiple .ts files contain type names (like Foo) that are the same. //file-a.ts type Foo = { } //file-b.ts type Foo = { } When attempting to compile, I encounter ...

elements that overlap exclusively in IE 8

Here's the information I need help with: http://jsfiddle.net/ktpmm5/Z5z8n/ The page can be accessed here: In IE 8, my paging element is shifted to the left and covers the heading. This issue does not occur in Chrome, FF, and Opera. I've been t ...

I am considering open-sourcing my website, but I am concerned about the file containing my database credentials

I developed a NextJS website that I am considering open sourcing, but I have sensitive credentials stored in a .env file for my database access. While I don't anticipate major issues if these credentials were exposed to the public, I prefer not to tak ...

Updating HTML label values using jQuery in a loop based on their index position

I am having an issue with my ajax call where I want to loop through each label in a class and set their value to the response returned from the server. However, the current code sets all labels to the same value instead of setting individual values based o ...

My function doesn't seem to be cooperating with async/await

const initialState={ isLoggedIn: false, userData: null, } function App() { const [state, setState]= useState(initialState) useEffect(()=>{ async function fetchUserData(){ await initializeUserInfo({state, setState}) // encountering an ...

Generate a fresh div and add pre-existing components

I currently have the following structure: <body> <div class="one"></div> <div class="two"></div> <div class="three"></div> </body> Using jQuery, I am trying to create a new <div class="fo ...

Implementing notifications in React JS

Hey there! I'm new to React JS and I need some guidance on how to add notification with action buttons in my PWA. Is there any specific way to achieve this in React JS? I have been attempting to integrate notifications into my progressive web app usi ...

Implementing Module Dependencies using RequireJS

I'm currently working with RequireJS and encountering some issues when trying to require local libraries. In my process, I've set up a JS file to import the library that was installed using npm JS function synthesizeToAudioFile() { ...