Using template literals to toggle CSS classes in React causes the button to malfunction

I'm working with a CSS module called 'styles' and this React code consists of a div containing two buttons. The state isMenuActive is used to determine if the menu is active or not. If the menu is active, the CSS class 'active' is applied and the menu appears; otherwise it does not.

  <div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
    <button onClick={() => { console.log('hi') }}>
      <span className="material-icons">edit</span>Edit
    </button>
    <button onClick={() => {console.log('hi')}}>
      <span className="material-icons">delete</span>Delete
    </button>
  </div>

When I click the buttons, nothing happens.

However, if I store the button as a global variable in developer tools and run button.click(), it works fine when the template literals are removed:

  <div className={styles.customerOptionsMenu + styles.active}>
    <button onClick={() => { console.log('hi') }}>
      <span className="material-icons">edit</span>Edit
    </button>
    <button onClick={() => {console.log('hi')}}>
      <span className="material-icons">delete</span>Delete
    </button>
  </div>

It works fine.

Why??? And what should I do to keep changing the classes when isMenuActive changes?

Edit: Full code with the button that changes isMenuActive

  const [isMenuActive, setIsMenuActive] = useState(false)
  const onBlur = () => { setIsMenuActive(!isMenuActive)}

  return(
    <td>
      <button onBlur={onBlur} className={styles.customerOptions} onClick={() => setIsMenuActive(!isMenuActive)}>
        <span className="material-icons">more_horiz</span>
      </button>
      <div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
        <button onClick={() => { console.log('hi') }}>
          <span className="material-icons">edit</span>Edit
        </button>
        <button onClick={() => {console.log('hi')}}>
          <span className="material-icons">delete</span>Delete
        </button>
      </div>
    </td>
  )

New edit: The answer is in the comments by Pandaiolo. The problem was the onBlur={onBlur} code, when I removed it from the button everything worked fine!

Answer №1

When dealing with changing classnames, one approach is to utilize the classnames library to achieve something like the following:

import cx from "classnames";

<div className={cx(styles.customerOptionsMenu, { styles["active"]: isMenuActive })}>
    <button onClick={() => { console.log('hi') }}>
      <span className="material-icons">edit</span>Edit
    </button>
    <button onClick={() => {console.log('hi')}}>
      <span className="material-icons">delete</span>Delete
    </button>
</div>

Answer №2

In my opinion, the spacing in your template literal looks good as it refers to two different class names. You may want to consider using

${isMenuActive ? styles.active :''}
instead of allowing null to become the string "null", which could cause unintended consequences if you have a class .null that applies certain styles.

It's possible that onBlur is triggered after the click event:

  1. Click
  2. Button gains focus
  3. Button blurs?

It's uncertain. If this is the case, it could result in toggling the state twice, nullifying its effect. Perhaps try starting with just the onClick without adding onBlur initially?

You can also insert a

console.log('isMenuActive', isMenuActive)
before the return statement to track its value during rerenders and ensure it aligns with your expectations.

Answer №3

The isMenuActive variable has not been defined. To fix this, ensure it is included as a parameter in the function like so:

export default function App(isMenuActive) {
  return (
    <div className="App">
  <div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
    <button onClick={() => { console.log('hi') }}>
      <span className="material-icons">edit</span>Edit
    </button>
    <button onClick={() => {console.log('hi')}}>
      <span className="material-icons">delete</span>Delete
    </button>
  </div>
    </div>
  );
}

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

Switch between display modes by clicking using collections

I am trying to figure out how to create a function that will only show content for the specific element in which my button is located. Currently, when I click the button it shows content for all elements with the 'one' class, but I want it to dis ...

Concentration hampers the ability to click the mouse

On a webpage, I am encountering an issue with text areas not allowing users to enter text. To address this, I implemented a code snippet that focuses on the textarea when clicked. However, this workaround only allows users to navigate using arrow keys an ...

Check if an array includes a specific value, and then either update it if found, or create it

I'm currently working with a Cart object in Javascript and I need to check if a specific item is present in the cart. Here's my approach: If the item is already in the cart, update its quantity. If it's not in the cart, add it to the items ...

Display a modal window in Bootstrap when the countdown timer reaches zero

I am facing another challenge. I am trying to set up a scenario where a countdown timer triggers a modal window to appear once it reaches 0. I have the codes for both the modal and the countdown timer, but I am struggling to figure out how to make them wo ...

Filter and orderBy functionality is not functioning properly in Angular UI Bootstrap Typeahead

Is it possible to implement a typeahead search feature for item names when the item details are fetched from another JSON object? Demo: http://codepen.io/anon/pen/PGWvmE While filter and orderBy functions are functioning correctly, I am facing challenges ...

Data vanishing in upcoming authentication session in test environment

I have encountered an issue with next auth in my next.js project. During development, the session data is lost if the server refreshes or if I switch to another tab and return to it. This forces me to sign out and then sign back in to restore the session d ...

What is the reason for the lack of uniqueness in Mongo ObjectIDs?

As per the documentation available from MongoDB, ObjectID's are supposed to be generated using a specific format: An ObjectID is a 96-bit number consisting of: a 4-byte timestamp representing seconds since the Unix epoch (up until the year 2106) a ...

The visibility of overflow-y does not seem to be working properly when overflow-x is

https://i.sstatic.net/hihjC.png .iati-list-table { overflow-x: auto; overflow-y: visible; } When I apply overflow-visible, a scroll bar appears. But when I use overflowy-hidden, the tooltip is cropped. How can I set it so that overflow x is auto a ...

Tips for Avoiding Inheritance of a Specific Method

Let's say we have two classes, A and B. Class B extends class A, inheriting all of its methods. It is also possible to override these inherited methods. The question at hand is whether it is possible to prevent class B from inheriting a specific metho ...

submit messages that have been sent before in the group chat

Currently, I am employed at a messaging application where I aim to save messages in an object structure like this : { 'room1': ['msg1', 'msg2', ...] 'room2': ['msg3', 'msg4', ...] ... } To ...

Is there a way to automatically scroll vertically to a specific line in HTML?

Trying to explain this is a bit tricky. I am looking to add an element to the HTML that prompts the browser to scroll vertically to its location automatically when loaded, similar to an anchor. So: | visible area | | content html | | content html | ...

Changing array element to undefined within an else if statement

I'm facing a puzzling issue while developing a web application in Node.js. The app is supposed to parse .csv files and insert them into a MySQL database. The problem arises at a particular point within the function: var router = require('express ...

Unable to compel attention towards entering data

How can I focus on an input after clicking on a span? The input is not initially visible, but becomes visible upon clicking the span. <form action="{{ route('busca') }}" method="get"> <span class="pesquisa-icon"></span> ...

What is the recommended approach for managing state in React when multiple components are trying to access and modify its data at the same time?

Issue: I am experiencing difficulty in adding new keys and/or values to the JSON editor or YAML editor when they both share and update the same state. The parent component sends JSON data to the child component through props import * as React from 'r ...

The full width of the Html body in tailwindcss is not being completely utilized

I am new to tailwindcss and encountering a problem. Please take a look at the screenshots provided; the background color is not being applied in the navbar and the HTML body is not displaying full width on medium and small screens. What's perplexing ...

Using AJAX to Access PHP Variables

I am working on creating a progress bar and have the following CSS code: #result{ background:#8c8f91; margin-left: 15px; margin-right: auto; table-layout: fixed; border-collapse: collapse; z-index: -1; position:relative; width: ...

Calculating the sum of all elements in an array

Hi, I am currently attempting to retrieve the total value from an array (such as Arr[1] + Arr[2], and so forth). Unfortunately, I am struggling to find a solution. Below is my existing function: this.hourlyTotals = function() { var custsperhour = Math ...

Why do I receive a URL like this when attempting to download a video from YouTube?

Can anyone explain to me why I am getting this URL error while trying to pull a video from YouTube? Error in console: GET http://localhost:3000/www.youtube.com/watch?v=IEDEtZ4UVtI 404 (Not Found) GET http://localhost:3000/www.youtube.com/watch?v=IEDEtZ4UVt ...

When using PHP, JavaScript, and HTML, you can trigger an image upload immediately after choosing a file using the

I currently have a small form with two buttons - one for browsing and another for uploading an image. I feel that having two separate buttons for this purpose is unnecessary. Is there a way to combine the browse and upload functions into just one button? ...

Make sure to load all necessary resources prior to loading the webpage

My inquiry is as follows: I have a single webpage containing numerous images in both small and large resolutions, utilized in HTML and CSS (e.g., as background images in CSS classes). Currently, I am looking to preload all the images on my site before it ...