Change the background-color of the whole app on button click React.js

Viewed 44

I am trying to change the color of the background of my whole React App on button click. However, I only change the color of the button itself. I am importing the App.css into my app and I want to dynamically change the CSS of the App from a separate function called ChangeColor. This function is then placed in my Header.js that is then placed in the App.js

Is there a way that I can do this? This is my code:

import React, {useState} from "react";
import Button from "react-bootstrap/esm/Button";
import '../../../App.css'

function ChangeColor() {
    const [isActive, setIsActive] = useState(false);
    const handleClick = () => {
        setIsActive(current => !current);
    };

    return(
        <Button 
            style={{
                backgroundColor: isActive ? 'red' : '',
                color: isActive ? 'white' : '',
            }}
            onClick={handleClick}
        > Test </Button>
    )
}

export default ChangeColor
.App {
  text-align: center;
  background-color: white;
}

3 Answers

There are a couple of solutions that come to mind.

  1. Store the background color in state, and toggle between the colours depending on the current state.

(Small note - you shouldn't call your component ChangeColor as it's not really representative of what the component is - changeColor might be a good name for a function. You should call your component ButtonChangeColor, for example.)

const { useState } = React;

function Example() {

  const [bgColor, setBgColor] = useState('white');

  function toggleBackground() {
    if (bgColor === 'white') setBgColor('black');
    if (bgColor === 'black') setBgColor('white');
  }

  const appStyle = ['App', bgColor].join(' ');

  return (
    <div className={appStyle}>
      <button onClick={toggleBackground}>
        Toggle background
      </button>
    </div>
  );

}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
.App {
  height: 100vh;
  background-color: white;
}

.black { background-color: black; }
<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>

  1. Use CSS variables and modify the current stylesheet using the CSSStyleDeclaration interface - no state required. We can usefully maintain the toggleBackground function outside of the component because it doesn't rely on state to work.

function toggleBackground() {
  const { style } = document.documentElement;
  const bgColor = style.getPropertyValue('--bg-color');
  if (bgColor === 'white' || bgColor === '') {
    style.setProperty('--bg-color', 'black');
  } else {
    style.setProperty('--bg-color', 'white');
  }
}

function Example() {
  return (
    <div className="App">
      <button onClick={toggleBackground}>
        Toggle background
      </button>
    </div>
  );
}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
:root { --bg-color: white; }

.App {
  height: 100vh;
  background-color: var(--bg-color);
}
<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>

The problem with your code is you are acting on the properties of the button. Instead you should act on the element its color you are trying to change.

In this code snippet the button modifies the color of the root div. Be aware that this solution is just to illustrate your problem. As has been stated by other users there are many ways to achieve what you want and some adhere to best practices while others not. Given the context of the question this answer just to points to why it is not working and not how best to do it. Please, refer to Andy's answer for more information about the latter.

const App = () => {
  const changeAppColor = () => {
    let el = document.getElementById("root");
    if (el.style.backgroundColor === "red") {
      el.style.backgroundColor = "unset";
    } else {
      el.style.backgroundColor = "red";
    }
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <button onClick={changeAppColor}>
        Change color
      </button>
    </div>
  );
}

ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <App />
);
<div id='root'> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

you can store isActive and color in localStorage

const [isActive, setIsActive] = useState(localStorage.getItem('is_active') || false);
    const handleClick = () => {
        setIsActive(current => !current);
    };


<Button 
      style={{
          backgroundColor: isActive ? 'red' : '',
          color: isActive ? localStorage.getItem('bg_color') : '',
      }}
      onClick={handleClick}
  > Test </Button>
Related