Alter the app's entire background color in React.js with a button click

I am facing an issue with changing the background color of my entire React App when a button is clicked. Currently, I am able to change the color of the button itself but not the background. I have imported the App.css file into my project and I am looking for a way to dynamically update the CSS of the App using a separate function called ChangeColor. This function is located in my Header.js which is then included in the App.js

Is there a solution to achieve this? Here is the code snippet:

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;
}

Answer №1

When considering ways to address this issue, a few solutions stand out.

  1. One option is to store the background color in the state and switch between colors based on the current state.

(A quick note - it's advisable not to name your component ChangeColor as it may not accurately reflect the component's purpose. Perhaps using ButtonChangeColor would be more appropriate.)

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. Alternatively, you can utilize CSS variables and adjust the current stylesheet through the CSSStyleDeclaration interface without needing to maintain state. The toggleBackground function can remain outside the component, independent of state requirements.

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>

Answer №2

To easily manage the state of isActive and color, consider utilizing localStorage for storage.

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>

Answer №3

Your code is experiencing an issue because you are manipulating the properties of the button instead of acting on the element whose color you intend to change.

Within this code snippet, the button is altering the color of the root div. It's important to note that this demonstration serves solely to highlight the problem at hand. There exist numerous approaches to achieving the desired outcome, some aligning with best practices more than others. The purpose of this response is simply to address why the current approach is ineffective, rather than prescribing the optimal method. For a comprehensive explanation, please refer to Andy's answer.

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>

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

Attempting the connected components with jest and react-testing-library

Looking to conduct testing on a connected React component using Jest, React Testing Library, and redux-mock-store. While attempting to access certain elements, encountering an error message: TestingLibraryElementError: Unable to locate an element with the ...

"Utilizing a JavaScript array to track the start of the week and

I am encountering a logic problem with determining the start of the week. Below is a snippet of the code: WeekStarts(WeekN) { let WeekBD = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Sa ...

Javascript malfunctioning - exhausted all troubleshooting options

My JavaScript code consists of a single line, but I keep encountering the "getElementById null" error. document.getElementById("menu-background").style.left = "0"; HTML: <html> <head> <title></title> <link rel="style ...

"Utilizing FileReader to seamlessly integrate data into FormData without the risk

Currently, I'm in the process of constructing an ajax file uploader. This is made possible thanks to the recently introduced FormData interface. Everything seems to work as expected when using the original file. However, I encounter issues when conver ...

Utilizing children as a prop within a Vue component

In React, I can create a FancyList component like this: const FancyList : React.SFC<{},{}> ({children}) => ( <ul> {...children} </ul> ); const FancyListItem : React.SFC<{text: string}, {}> ({children}) => < ...

Choose all the HTML content that falls within two specific tags

Similar Question: jquery - How to select all content between two tags Let's say there is a sample HTML code as follows: <div> <span> <a>Link</a> </span> <p id="start">Foo</p> <!-- lots of random HTML ...

Maintain the functionality, but disable all stylesheets and scripts

I have 4 separate pages, each with their own distinct stylesheets and scripts that I switch between using ajax and historyPopState. The issue is that downloading them repeatedly can be inefficient. I am seeking a solution to keep the stylesheets and scri ...

$routeProvider - providing controller dependencies based on the URL path

Take a look at the following code snippet: var app = angular.module("app", [], function($routeProvider) { $routeProvider .when("/page1", { controller: "MyController" }) .when("/page2", { controller: "MyController" }) .when("/page3", { contro ...

Arranging an array based on numerical values embedded in strings

My array is as follows: var arr = [ '4msterdam', 'Par1s', 'N3w York', '2urich']; Is there a way to sort the elements of this array based on the numbers included in each string? ...

Implement the TypeScript handleChange function for input fields and dropdown menus

Currently, I am in the process of developing a form using TypeScript and Material-UI components. My objective is to create a change handler function that can be utilized for both select and textfield changes. Below are my state and functions: const [re ...

Adjust the element based on hover over the pseudo element

Looking to modify an element based on the hover state of a pseudo-element. Here's what I've tried so far, but it isn't working as expected: nav .logo { display: none; } nav:before{} nav:hover:before .logo { display: block; } I want th ...

Save property using the useState hook

I am working on implementing a sorting function in the child component, where the props are passed in from the parent through an axios call. Should I: Store the prop in the child component's useState? Pass the parent's setState function as a pro ...

What is the best way to encapsulate a slider within a fragment to prevent the occurrence of the "Type 'Element[]' is not assignable to type 'ReactNode'" error?

I'm encountering an issue with a Slider component in a NextJs landing page template. Every time I try to map through an array within the Slider component, I receive an error. I've attempted to find solutions online and came across this related th ...

Is it possible to incorporate an existing svg from the page into another svg element?

Currently, I am facing a challenge where I am programmatically creating logos as svgs with d3. Now, I have an svg map and I want to incorporate these logos into it. I am wondering if there is a way, whether through d3 or another method, to transfer these ...

The Gatsby + Typescript project is reporting that the module with the name "*.module.scss" does not have any exported members

I've recently gone through Gatsby's demo project in their documentation (which is long overdue for an update). I've carefully followed the instructions provided here: I've included an index.d.ts file in the /src directory of my project ...

Determine if a mobile application has been installed using Vue.js

I am currently developing a web application and have implemented a check to determine whether the user is accessing it from a mobile device or laptop. Let's consider the link as: my-site.com In addition to the web version, my site also offers a mobi ...

How to stop crosshair line at the intersection point of x and y axes on a line graph using Highcharts

I feel like using an image would help better illustrate my question. https://i.stack.imgur.com/LJN12.png Whenever I enable crosshairs, they extend from the bottom of the chart to the top. Is there a way to create a crosshair that only intersects at the x ...

Instructions for transforming rows into columns in JSON format

Looking to convert an array of JSON objects into a format where rows become columns and the values at the side become column values, similar to the crosstab function in PostgreSQL. The JSON data looks something like this: {"marketcode":"01","size":"8,5", ...

Why is the 'a' element not clickable after the AJAX complete function has executed in JavaScript?

I have a small question regarding my use of AJAX. Everything is working fine, but after the AJAX request completes, I am trying to change the element attributes such as backgroundImage dynamically. Although this process works correctly, the element that wa ...

Using Vue.js to group JSON arrays multiple times

I have a program that I utilize to import a CSV data file and then convert it into JSON format. The resulting JSON structure is as follows: { "Class": "Cultivated Mushrooms", "Type": "Shii-take", "Grade": "Medium", "LvH": "SP", "Description": " ...