Home > Mobile >  React Toggle Body Class with button
React Toggle Body Class with button

Time:01-27

I'm still learning React but I'm having an issue toggling a body class with a button in the menu.

const toggleSideMenu = event => {
        // toggle class on click
        //Below is not correct
        event.getElementsByTagName('body').classList.toggle('sb-sidenav-toggled');
      };`


<button onClick={toggleSideMenu} id="sidebarToggle" href="#!"><i className="fas fa-bars"></i></button>

I'm used to doing this easily in jQuery but it's not recommended to use jQuery in React because of the dom. I would appreciate any suggestions.

Thanks so much!

CodePudding user response:

In this example, we are using the useState hook to keep track of the toggle state. The initial state is set to false. We are using the isToggled state in the JSX to determine what to render on the screen, and to update the text of the button.

We have an onClick event on the button, which calls the setIsToggled function and pass the negation of the current state (!isToggled), this is the way to toggle the state, every time the button is clicked.

import React, { useState } from 'react';

const MyComponent = () => {
  // useState hook to keep track of the toggle state
  const [isToggled, setIsToggled] = useState(false);

  return (
    <div>
      {/* render some content or change className based on the toggle state */}
      <p className={isToggled? "class1" : "classB">Toggled on</p>

      <button onClick={() => setIsToggled(!isToggled)}>
        {isToggled ? 'Turn off' : 'Turn on'}
      </button>
    </div>
  );
}

export default MyComponent;

But if you need to do something more advanced, maybe you can learn more about React Context.

import React, { useState } from 'react';

// Create a context to share the toggle state
const ToggleContext = React.createContext();

const MyApp = () => {
  // useState hook to keep track of the toggle state
  const [isToggled, setIsToggled] = useState(false);

  return (
    <ToggleContext.Provider value={{ isToggled, setIsToggled }}>
      <MyComponent1 />
      <MyComponent2 />
      {/* any other components that need access to the toggle state */}
    </ToggleContext.Provider>
  );
}

const MyComponent1 = () => {
  // use the toggle state and toggle function from the context
  const { isToggled, setIsToggled } = useContext(ToggleContext);

  return (
    <div>
      <p className={isToggled? "class1" : "classB">Toggled on</p>
      <button onClick={() => setIsToggled(!isToggled)}>
        {isToggled ? 'Turn off' : 'Turn on'}
      </button>
    </div>
  );
}

const MyComponent2 = () => {
  // use the toggle state from the context
  const { isToggled } = useContext(ToggleContext);

  return (
    <div>
      {isToggled ? <p>Toggled on</p> : <p>Toggled off</p>}
    </div>
  );
}

export default MyApp;

CodePudding user response:

A very basic example to show you how to use state to maintain whether a menu should be open or not.

It has one button that when clicked calls a function that updates the state.

It has one Menu component that accepts that state, and uses CSS to determine whether it should be "open" (ie on/off screen).

Like I said, as simple as I could make it.

const { useState } = React;

function Example() {

  // The state set to either true or false
  // Initially it's false / menu closed
  const [ menuOpen, setMenuOpen ] = useState(false);

  // When the button is clicked we take the
  // previous state and toggle it - either from true
  // to false, or vice versa
  function handleClick() {
    setMenuOpen(prev => !prev);
  }

  // One Menu component that accepts that state
  // and one button that updates the state
  return (
    <div>
      <Menu open={menuOpen} />
      <button onClick={handleClick}>
        Toggle Sidebar Menu
      </button>
    </div>
  );

}

// Small menu (an aside element) which uses CSS
// to work out its position on the screen
// It does this by creating a classList using the default
// "menu" which it ties together with "open" but it only
// adds that if the state is true
// And then just use that joined array as the className on
// the element
// You can see in the CSS what both those classes do
function Menu({ open }) {
  
  const menuStyle = [
    'menu',
    open && 'open'
  ].join(' ');
  
  return (
    <aside className={menuStyle}>
      I am a sidebar
    </aside>
  );

}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
.menu { width: 100px; top: 0px; left: -120px; background-color: salmon; position: fixed; height: 100vh; padding: 10px; transition-property: left; transition-duration: 0.25s;}
.open { left: 0px; }
button { position: fixed; left: 150px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

CodePudding user response:

getElementsByTagName() is method of Document or Element, not react event.

What you need to do, is to look for body inside document.

Also getElementsByTagName(), returns HTMLCollection (many elements), so you need to grab first one (usually there is only one body element on page)

document.getElementsByTagName('body')[0].classList.toggle('sb-sidenav-toggled');

There is also shortcut for body element document.body, so it can be also written as:

document.body.classList.toggle('sb-sidenav-toggled');
  • Related