1

This is Header component with React-Bootstrap. I created a menu icon with pure CSS but I want to change the icon function onClick but I'm getting the error - TypeError: Cannot read property 'toggle' of undefined . It's there any way I'm getting it wrongly? Kindly check. Thanks.

Also, it's there a way, I can handle this with React Hooks method instead?

Thanks.

import styles from './Landing.module.css';
import './Landing.module.css';;

const openMenu = (open) => {
    open.classList.toggle('change');
};

 <Nav className="ml-auto">
  <div className={styles.allMenus}>
    <div className="menuIcon" onClick={openMenu}>
       <div className={styles.bar1}></div>
         <div className={styles.bar2}></div>
           <div className={styles.bar3}></div>
         </div>
      </div>
 </Nav>

My CSS - It has the change styles

div[class="menuIcon"] {
    background-color: #ffffff;
    padding: 13px;
    margin-right: 46px;
    float: right;
    cursor: pointer;
}

.bar1, .bar2, .bar3 {
    width: 32px;
    height: 3px;
    background-color: #333;
    margin: 6px 0;
    transition: 0.4s;
}

.change .bar1 {
    -webkit-transform: rotate(-45deg) translate(-9px, 6px) ;
    transform: rotate(-45deg) translate(-9px, 6px) ;
}
  
.change .bar2 {
    opacity: 0;
}
  
.change .bar3 {
    -webkit-transform: rotate(45deg) translate(-8px, -8px) ;
    transform: rotate(45deg) translate(-8px, -8px) ;
}
1
  • className="menuIcon" is that how classNames are declared?! In standard HTML, its simply class="my_class". I would change that... and give it a try. Especially given that it looks like you are trying to use a javascript function... Commented Jan 27, 2021 at 17:29

1 Answer 1

1

You are trying to use the DOM's classList in React, but react JSX elements are not DOM elements, but an XML based markup that is translated to JS.

In React you'll need to use state/props to control the behaviour, and add or remove the classes.

In the example I'm using the useState() hook to toggle a boolean, and then I add or remove the class name in the template string.

You can use a library, such as classnames to prevent yourself from writing lots of template strings with class names.

const { useState } = React;

const styles = {
  menuIcon: 'menuIcon',
  change: 'change',
  bar1: 'bar1',
  bar2: 'bar2',
  bar3: 'bar3',
};

const Demo = () => {
  const [changed, setChange] = useState(false);
  
  const openMenu = (open) => {
    setChange(c => !c);
  };

  return (
    <nav className="ml-auto">
      <div className="allMenus">
        <div className={`${styles.menuIcon} ${changed ? styles.change : ''}`} onClick={openMenu}>
          <div className={styles.bar1}></div>
          <div className={styles.bar2}></div>
          <div className={styles.bar3}></div>
        </div>
      </div>
    </nav>
  );
}

ReactDOM.render(
  <Demo />,
  root
);
.menuIcon {
  padding: 13px;
  margin-right: 46px;
  float: right;
  cursor: pointer;
}

.bar1,
.bar2,
.bar3 {
  width: 32px;
  height: 3px;
  background-color: #333;
  margin: 6px 0;
  transition: 0.4s;
}

.change .bar1 {
  -webkit-transform: rotate(-45deg) translate(-9px, 6px);
  transform: rotate(-45deg) translate(-9px, 6px);
}

.change .bar2 {
  opacity: 0;
}

.change .bar3 {
  -webkit-transform: rotate(45deg) translate(-8px, -8px);
  transform: rotate(45deg) translate(-8px, -8px);
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

Sign up to request clarification or add additional context in comments.

8 Comments

This works. But in my case, the styles are not getting applied. All the styles didn't work, when I inspected the element, the change got applied to the menu-icon but the styles didn't work with it.
You are using variables (styles) and not strings. Don't wrap them with quotes.
Could it be because I'm using className as - className={styles.theStyleName}? I'm still not getting it.
Try changing the className to className={styles.bar1} and the rest. I'd have gone with strings but I'm using a CSS framework.
styles.allMenus is a string because that's what className accepts. Try to console.log(styles), and you'll see that it's an object with string properties.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.